diff options
author | handbrake <[email protected]> | 2006-01-14 13:21:55 +0000 |
---|---|---|
committer | handbrake <[email protected]> | 2006-01-14 13:21:55 +0000 |
commit | dc8de40de13c3f3e643b980a95ef48ccafb542e3 (patch) | |
tree | 953b97afe7082bbe2ce4247c703a51aa8e29a3c9 /core/FfmpegEnc.c | |
parent | 4beb6a8b483c9d84677b21cc271ce315f136335c (diff) |
HandBrake 0.6.0-test1
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@10 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'core/FfmpegEnc.c')
-rw-r--r-- | core/FfmpegEnc.c | 293 |
1 files changed, 172 insertions, 121 deletions
diff --git a/core/FfmpegEnc.c b/core/FfmpegEnc.c index 2118c29d6..4028dc5fb 100644 --- a/core/FfmpegEnc.c +++ b/core/FfmpegEnc.c @@ -1,38 +1,40 @@ -/* $Id: FfmpegEnc.c,v 1.5 2003/11/06 13:03:19 titer Exp $ +/* $Id: FfmpegEnc.c,v 1.18 2004/01/21 17:59:33 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#include "FfmpegEnc.h" -#include "Fifo.h" -#include "Work.h" +#include "HBInternal.h" -#include <ffmpeg/avcodec.h> +/* libavcodec */ +#include "ffmpeg/avcodec.h" -/* Extern functions */ -void HBSetPosition( HBHandle *, float ); - -/* Local prototypes */ -static int FfmpegEncWork( HBWork * ); - -struct HBFfmpegEnc +typedef struct HBFfmpegEnc { HB_WORK_COMMON_MEMBERS - HBHandle * handle; - HBTitle * title; + HBHandle * handle; + HBTitle * title; - HBBuffer * mpeg4Buffer; - int pass; + HBBuffer * mpeg4Buffer; + int pass; AVCodecContext * context; - FILE * file; -}; + FILE * file; + + /* Stats */ + int frames; + int64_t bytes; +} HBFfmpegEnc; -HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title ) +/* Local prototypes */ +static int FfmpegEncWork( HBWork * ); +static int InitAvcodec( HBFfmpegEnc * ); +static void CloseAvcodec( HBFfmpegEnc * ); + +HBWork * HBFfmpegEncInit( HBHandle * handle, HBTitle * title ) { HBFfmpegEnc * f; - if( !( f = malloc( sizeof( HBFfmpegEnc ) ) ) ) + if( !( f = calloc( sizeof( HBFfmpegEnc ), 1 ) ) ) { HBLog( "HBFfmpegEncInit: malloc() failed, gonna crash" ); return NULL; @@ -42,31 +44,32 @@ HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title ) f->work = FfmpegEncWork; f->handle = handle; - f->title = title; - - f->mpeg4Buffer = NULL; - f->pass = 42; - f->context = NULL; - f->file = NULL; + f->title = title; + f->pass = 42; - return f; + return (HBWork*) f; } -void HBFfmpegEncClose( HBFfmpegEnc ** _f ) +void HBFfmpegEncClose( HBWork ** _f ) { - HBFfmpegEnc * f = *_f; + HBFfmpegEnc * f = (HBFfmpegEnc*) *_f; if( f->context ) { - HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", - f->pass ); + CloseAvcodec( f ); + } - avcodec_close( f->context ); - if( f->file ) - { - fclose( f->file ); - f->file = NULL; - } + /* Stats */ + if( f->frames ) + { + float bitrate = (float) f->bytes * f->title->rate / + f->frames / f->title->rateBase / 128; + int64_t bytes = (int64_t) f->frames * f->title->bitrate * 128 * + f->title->rateBase / f->title->rate; + + HBLog( "HBFfmpegEnc: %d frames encoded (%lld bytes), %.2f kbps", + f->frames, f->bytes, bitrate ); + HBLog( "HBFfmpegEnc: error is %lld bytes", f->bytes - bytes ); } free( f->name ); free( f ); @@ -87,7 +90,7 @@ static int FfmpegEncWork( HBWork * w ) if( f->mpeg4Buffer ) { - if( HBFifoPush( title->mpeg4Fifo, &f->mpeg4Buffer ) ) + if( HBFifoPush( title->outFifo, &f->mpeg4Buffer ) ) { didSomething = 1; } @@ -109,94 +112,26 @@ static int FfmpegEncWork( HBWork * w ) /* Init or re-init if needed */ if( scaledBuffer->pass != f->pass ) { - AVCodec * codec; - AVCodecContext * context; - if( f->context ) { - HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", - f->pass ); - - avcodec_close( f->context ); - if( f->file ) - { - fclose( f->file ); - f->file = NULL; - } + CloseAvcodec( f ); } - + f->pass = scaledBuffer->pass; - - HBLog( "HBFfmpegEnc: opening libavcodec (pass %d)", f->pass ); - codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); - if( !codec ) + + if( !InitAvcodec( f ) ) { - HBLog( "HBFfmpegEnc: avcodec_find_encoder() failed" ); HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); return didSomething; } - - context = avcodec_alloc_context(); - context->bit_rate = 1024 * title->bitrate; - context->bit_rate_tolerance = 10240 * title->bitrate; - context->width = title->outWidth; - context->height = title->outHeight; - context->frame_rate = title->rate; - context->frame_rate_base = title->rateBase; - context->gop_size = 10 * title->rate / - title->rateBase; - - if( f->pass ) - { - char fileName[1024]; memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", - HBGetPid( f->handle ) ); - - if( f->pass == 1 ) - { - f->file = fopen( fileName, "w" ); - - context->flags |= CODEC_FLAG_PASS1; - } - else - { - FILE * file; - int size; - char * log; - - file = fopen( fileName, "r" ); - fseek( file, 0, SEEK_END ); - size = ftell( file ); - fseek( file, 0, SEEK_SET ); - if( !( log = malloc( size + 1 ) ) ) - { - HBLog( "HBFfmpegEnc: malloc() failed, gonna crash" ); - } - log[size] = '\0'; - fread( log, size, 1, file ); - fclose( file ); - - context->flags |= CODEC_FLAG_PASS2; - context->stats_in = log; - } - } - - if( avcodec_open( context, codec ) < 0 ) - { - HBLog( "HBFfmpegEnc: avcodec_open() failed" ); - HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); - return didSomething; - } - - f->context = context; } - frame = avcodec_alloc_frame(); - frame->data[0] = scaledBuffer->data; - frame->data[1] = frame->data[0] + title->outWidth * - title->outHeight; - frame->data[2] = frame->data[1] + title->outWidth * - title->outHeight / 4; + frame = avcodec_alloc_frame(); + frame->data[0] = scaledBuffer->data; + frame->data[1] = frame->data[0] + title->outWidth * + title->outHeight; + frame->data[2] = frame->data[1] + title->outWidth * + title->outHeight / 4; frame->linesize[0] = title->outWidth; frame->linesize[1] = title->outWidth / 2; frame->linesize[2] = title->outWidth / 2; @@ -204,9 +139,8 @@ static int FfmpegEncWork( HBWork * w ) mpeg4Buffer = HBBufferInit( 3 * title->outWidth * title->outHeight / 2 ); mpeg4Buffer->position = scaledBuffer->position; - mpeg4Buffer->size = - avcodec_encode_video( f->context, mpeg4Buffer->data, - mpeg4Buffer->alloc, frame ); + mpeg4Buffer->size = avcodec_encode_video( f->context, + mpeg4Buffer->data, mpeg4Buffer->alloc, frame ); mpeg4Buffer->keyFrame = f->context->coded_frame->key_frame; /* Inform the GUI about the current position */ @@ -220,11 +154,128 @@ static int FfmpegEncWork( HBWork * w ) } HBBufferClose( &mpeg4Buffer ); } + else + { + f->mpeg4Buffer = mpeg4Buffer; + + /* Stats */ + f->frames++; + f->bytes += mpeg4Buffer->size; + } HBBufferClose( &scaledBuffer ); free( frame ); - f->mpeg4Buffer = mpeg4Buffer; - return didSomething; } + +static int InitAvcodec( HBFfmpegEnc * f ) +{ + AVCodec * codec; + AVCodecContext * context; + HBTitle * title = f->title; + + HBLog( "HBFfmpegEnc: opening libavcodec (pass %d)", f->pass ); + + codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); + if( !codec ) + { + HBLog( "HBFfmpegEnc: avcodec_find_encoder() failed" ); + HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); + return 0; + } + + context = avcodec_alloc_context(); + context->bit_rate = 1024 * title->bitrate; + context->bit_rate_tolerance = 10 * context->bit_rate; + context->width = title->outWidth; + context->height = title->outHeight; + context->frame_rate = title->rate; + context->frame_rate_base = title->rateBase; + context->gop_size = 10 * title->rate / title->rateBase; + + if( title->mux == HB_MUX_MP4 && f->pass != 1 ) + { + context->flags |= CODEC_FLAG_GLOBAL_HEADER; + } + + if( f->pass ) + { + char fileName[1024]; memset( fileName, 0, 1024 ); + sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", + HBGetPid( f->handle ) ); + + if( f->pass == 1 ) + { + f->file = fopen( fileName, "w" ); + context->flags |= CODEC_FLAG_PASS1; + } + else + { + FILE * file; + int size; + char * log; + + file = fopen( fileName, "r" ); + fseek( file, 0, SEEK_END ); + size = ftell( file ); + fseek( file, 0, SEEK_SET ); + if( !( log = malloc( size + 1 ) ) ) + { + HBLog( "HBFfmpegEnc: malloc() failed, gonna crash" ); + } + log[size] = '\0'; + fread( log, size, 1, file ); + fclose( file ); + + context->flags |= CODEC_FLAG_PASS2; + context->stats_in = log; + } + } + +#ifdef HB_NOMMX + context->dct_algo = FF_DCT_INT; + context->idct_algo = FF_IDCT_INT; + context->dsp_mask = 0x1F; +#endif + + if( avcodec_open( context, codec ) < 0 ) + { + HBLog( "HBFfmpegEnc: avcodec_open() failed" ); + return 0; + } + + if( title->mux == HB_MUX_MP4 && f->pass != 1 ) + { + /* UGLY */ + title->esConfig = malloc( 15 ); + title->esConfigLength = 15; + memcpy( title->esConfig, context->extradata + 15, 15 ); + } + + f->context = context; + return 1; +} + +static void CloseAvcodec( HBFfmpegEnc * f ) +{ + HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", + f->pass ); + + if( f->context->stats_in ) + { + free( f->context->stats_in ); + } + avcodec_close( f->context ); + if( f->file ) + { + fclose( f->file ); + f->file = NULL; + } + if( f->title->esConfig ) + { + free( f->title->esConfig ); + f->title->esConfigLength = 0; + } +} + |