X-Git-Url: http://research.m1stereo.tv/gitweb?a=blobdiff_plain;f=src%2Fmodules%2Favformat%2Fconsumer_avformat.c;h=5a1ab27201c5faf0709a8cdee2eae8f2e7f9f9ca;hb=d33f444d4ef4c7bc4074d07a49eca0ab7d108394;hp=21242c665cbea2d123cd622e20f352d2f7108ddd;hpb=17c07b3e1ea8b4d92e87789fb757c65051f2a38e;p=melted diff --git a/src/modules/avformat/consumer_avformat.c b/src/modules/avformat/consumer_avformat.c index 21242c6..5a1ab27 100644 --- a/src/modules/avformat/consumer_avformat.c +++ b/src/modules/avformat/consumer_avformat.c @@ -3,25 +3,23 @@ * Copyright (C) 2003-2004 Ushodaya Enterprises Limited * Author: Charles Yates * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. * - * This program is distributed in the hope that it will be useful, + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -// Local header files -#include "consumer_avformat.h" - // mlt Header files +#include #include // System header files @@ -35,6 +33,9 @@ // avformat header files #include +#ifdef SWSCALE +#include +#endif // // This structure should be extended and made globally available in mlt @@ -133,10 +134,10 @@ static void consumer_close( mlt_consumer this ); /** Initialise the dv consumer. */ -mlt_consumer consumer_avformat_init( char *arg ) +mlt_consumer consumer_avformat_init( mlt_profile profile, char *arg ) { // Allocate the consumer - mlt_consumer this = mlt_consumer_new( ); + mlt_consumer this = mlt_consumer_new( profile ); // If memory allocated and initialises without error if ( this != NULL ) @@ -161,7 +162,7 @@ mlt_consumer consumer_avformat_init( char *arg ) mlt_properties_set_int( properties, "gop_size", 12 ); mlt_properties_set_int( properties, "b_frames", 0 ); mlt_properties_set_int( properties, "mb_decision", FF_MB_DECISION_SIMPLE ); - mlt_properties_set_double( properties, "qscale", 1 ); + mlt_properties_set_double( properties, "qscale", 0 ); mlt_properties_set_int( properties, "me_method", ME_EPZS ); mlt_properties_set_int( properties, "mb_cmp", FF_CMP_SAD ); mlt_properties_set_int( properties, "ildct_cmp", FF_CMP_VSAD ); @@ -189,10 +190,10 @@ mlt_consumer consumer_avformat_init( char *arg ) mlt_properties_set_int( properties, "video_rc_buffer_size", 0 ); mlt_properties_set_double( properties, "video_rc_buffer_aggressivity", 1.0 ); mlt_properties_set_double( properties, "video_rc_initial_cplx", 0 ); - mlt_properties_set_double( properties, "video_i_qfactor", 1.25 ); + mlt_properties_set_double( properties, "video_i_qfactor", -0.8 ); mlt_properties_set_double( properties, "video_b_qfactor", 1.25 ); - mlt_properties_set_double( properties, "video_i_qoffset", -0.8 ); - mlt_properties_set_double( properties, "video_b_qoffset", 0 ); + mlt_properties_set_double( properties, "video_i_qoffset", 0 ); + mlt_properties_set_double( properties, "video_b_qoffset", 1.25 ); mlt_properties_set_int( properties, "video_intra_quant_bias", FF_DEFAULT_QUANT_BIAS ); mlt_properties_set_int( properties, "video_inter_quant_bias", FF_DEFAULT_QUANT_BIAS ); mlt_properties_set_int( properties, "dct_algo", 0 ); @@ -208,6 +209,8 @@ mlt_consumer consumer_avformat_init( char *arg ) mlt_properties_set_int( properties, "coder", 0 ); mlt_properties_set_int( properties, "context", 0 ); mlt_properties_set_int( properties, "predictor", 0 ); + mlt_properties_set_int( properties, "ildct", 0 ); + mlt_properties_set_int( properties, "ilme", 0 ); // Ensure termination at end of the stream mlt_properties_set_int( properties, "terminate_on_pause", 1 ); @@ -492,6 +495,7 @@ static AVStream *add_video_stream( mlt_consumer this, AVFormatContext *oc, int c c->rc_max_rate = mlt_properties_get_int( properties, "video_rc_max_rate" ); c->rc_min_rate = mlt_properties_get_int( properties, "video_rc_min_rate" ); c->rc_buffer_size = mlt_properties_get_int( properties, "video_rc_buffer_size" ); + c->rc_initial_buffer_occupancy = c->rc_buffer_size*3/4; c->rc_buffer_aggressivity= mlt_properties_get_double( properties, "video_rc_buffer_aggressivity" ); c->rc_initial_cplx= mlt_properties_get_double( properties, "video_rc_initial_cplx" ); c->i_quant_factor = mlt_properties_get_double( properties, "video_i_qfactor" ); @@ -514,6 +518,14 @@ static AVStream *add_video_stream( mlt_consumer this, AVFormatContext *oc, int c c->context_model= mlt_properties_get_int( properties, "context" ); c->prediction_method= mlt_properties_get_int( properties, "predictor" ); c->me_method = mlt_properties_get_int( properties, "me_method" ); + if ( mlt_properties_get_int( properties, "progressive" ) == 0 && + mlt_properties_get_int( properties, "deinterlace" ) == 0 ) + { + if ( mlt_properties_get_int( properties, "ildct" ) ) + c->flags |= CODEC_FLAG_INTERLACED_DCT; + if ( mlt_properties_get_int( properties, "ilme" ) ) + c->flags |= CODEC_FLAG_INTERLACED_ME; + } } else { @@ -609,7 +621,7 @@ static void *consumer_thread( void *arg ) struct timeval ante; // Get the frame rate - int fps = mlt_properties_get_double( properties, "fps" ); + double fps = mlt_properties_get_double( properties, "fps" ); // Get width and height int width = mlt_properties_get_int( properties, "width" ); @@ -939,7 +951,15 @@ static void *consumer_thread( void *arg ) } // Do the colour space conversion +#ifdef SWSCALE + struct SwsContext *context = sws_getContext( width, height, PIX_FMT_YUV422, + width, height, video_st->codec->pix_fmt, SWS_FAST_BILINEAR, NULL, NULL, NULL); + sws_scale( context, input->data, input->linesize, 0, height, + output->data, output->linesize); + sws_freeContext( context ); +#else img_convert( ( AVPicture * )output, video_st->codec->pix_fmt, ( AVPicture * )input, PIX_FMT_YUV422, width, height ); +#endif // Apply the alpha if applicable if ( video_st->codec->pix_fmt == PIX_FMT_RGBA32 ) @@ -992,6 +1012,10 @@ static void *consumer_thread( void *arg ) // Set the quality output->quality = video_st->quality; + // Set frame interlace hints + output->interlaced_frame = !mlt_properties_get_int( frame_properties, "progressive" ); + output->top_field_first = mlt_properties_get_int( frame_properties, "top_field_first" ); + // Encode the image out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, output ); @@ -1045,6 +1069,70 @@ static void *consumer_thread( void *arg ) } } +#ifdef FLUSH + if ( ! real_time_output ) + { + // Flush audio fifo + if ( audio_st && audio_st->codec->frame_size > 1 ) for (;;) + { + AVCodecContext *c = audio_st->codec; + AVPacket pkt; + av_init_packet( &pkt ); + pkt.size = 0; + + if ( /*( c->capabilities & CODEC_CAP_SMALL_LAST_FRAME ) &&*/ + ( channels * audio_input_frame_size < sample_fifo_used( fifo ) ) ) + { + sample_fifo_fetch( fifo, buffer, channels * audio_input_frame_size ); + pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, buffer ); + } + if ( pkt.size <= 0 ) + pkt.size = avcodec_encode_audio( c, audio_outbuf, audio_outbuf_size, NULL ); + if ( pkt.size <= 0 ) + break; + + // Write the compressed frame in the media file + if ( c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE ) + pkt.pts = av_rescale_q( c->coded_frame->pts, c->time_base, audio_st->time_base ); + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index = audio_st->index; + pkt.data = audio_outbuf; + if ( av_interleaved_write_frame( oc, &pkt ) != 0 ) + { + fprintf(stderr, "Error while writing flushed audio frame\n"); + break; + } + } + + // Flush video + if ( video_st && !( oc->oformat->flags & AVFMT_RAWPICTURE ) ) for (;;) + { + AVCodecContext *c = video_st->codec; + AVPacket pkt; + av_init_packet( &pkt ); + + // Encode the image + pkt.size = avcodec_encode_video( c, video_outbuf, video_outbuf_size, NULL ); + if ( pkt.size <= 0 ) + break; + + if ( c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE ) + pkt.pts= av_rescale_q( c->coded_frame->pts, c->time_base, video_st->time_base ); + if( c->coded_frame && c->coded_frame->key_frame ) + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index = video_st->index; + pkt.data = video_outbuf; + + // write the compressed frame in the media file + if ( av_interleaved_write_frame( oc, &pkt ) != 0 ) + { + fprintf(stderr, "Error while writing flushed video frame\n"); + break; + } + } + } +#endif + // close each codec if (video_st) close_video(oc, video_st); @@ -1060,7 +1148,11 @@ static void *consumer_thread( void *arg ) // Close the output file if (!(fmt->flags & AVFMT_NOFILE)) +#if LIBAVFORMAT_VERSION_INT >= ((52<<16)+(0<<8)+0) + url_fclose(oc->pb); +#else url_fclose(&oc->pb); +#endif // Clean up input and output frames if ( output )