summaryrefslogtreecommitdiffstats
path: root/core/Mpeg4Encoder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/Mpeg4Encoder.cpp')
-rw-r--r--core/Mpeg4Encoder.cpp150
1 files changed, 150 insertions, 0 deletions
diff --git a/core/Mpeg4Encoder.cpp b/core/Mpeg4Encoder.cpp
new file mode 100644
index 000000000..42fb38b9e
--- /dev/null
+++ b/core/Mpeg4Encoder.cpp
@@ -0,0 +1,150 @@
+/* $Id: Mpeg4Encoder.cpp,v 1.15 2003/09/30 14:38:15 titer Exp $
+
+ This file is part of the HandBrake source code.
+ Homepage: <http://beos.titer.org/handbrake/>.
+ It may be used under the terms of the GNU General Public License. */
+
+#include "Mpeg4Encoder.h"
+#include "Manager.h"
+#include "Fifo.h"
+
+#include <ffmpeg/avcodec.h>
+
+HBMpeg4Encoder::HBMpeg4Encoder( HBManager * manager, HBTitle * title )
+ : HBThread( "mpeg4encoder" )
+{
+ fManager = manager;
+ fTitle = title;
+}
+
+void HBMpeg4Encoder::DoWork()
+{
+ if( !( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) )
+ {
+ return;
+ }
+
+ fPass = fResizedBuffer->fPass;
+ Init();
+
+ do
+ {
+ while( fSuspend )
+ {
+ Snooze( 10000 );
+ }
+
+ if( fResizedBuffer->fPass != fPass )
+ {
+ Close();
+ fPass = fResizedBuffer->fPass;
+ Init();
+ }
+
+ fManager->SetPosition( fResizedBuffer->fPosition );
+ EncodeBuffer();
+ }
+ while( ( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) );
+}
+
+void HBMpeg4Encoder::Init()
+{
+ AVCodec * codec = avcodec_find_encoder( CODEC_ID_MPEG4 );
+ if( !codec )
+ {
+ Log( "HBMpeg4Encoder: avcodec_find_encoder() failed" );
+ fManager->Error();
+ return;
+ }
+
+ fContext = avcodec_alloc_context();
+ fContext->bit_rate = 1024 * fTitle->fBitrate;
+ fContext->bit_rate_tolerance = 1024 * fTitle->fBitrate;
+ fContext->width = fTitle->fOutWidth;
+ fContext->height = fTitle->fOutHeight;
+ fContext->frame_rate = fTitle->fRate;
+ fContext->frame_rate_base = fTitle->fScale;
+ fContext->gop_size = 10 * fTitle->fRate / fTitle->fScale;
+
+ if( fPass == 1 )
+ {
+ fContext->flags |= CODEC_FLAG_PASS1;
+
+ char fileName[1024]; memset( fileName, 0, 1024 );
+ sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", fManager->GetPid() );
+ fFile = fopen( fileName, "w" );
+ }
+ else if( fPass == 2 )
+ {
+ fContext->flags |= CODEC_FLAG_PASS2;
+
+ char fileName[1024]; memset( fileName, 0, 1024 );
+ sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", fManager->GetPid() );
+ fFile = fopen( fileName, "r" );
+ fseek( fFile, 0, SEEK_END );
+ uint32_t size = ftell( fFile );
+ fLog = (char*) malloc( size + 1 );
+ fseek( fFile, 0, SEEK_SET );
+ fread( fLog, size, 1, fFile );
+ fclose( fFile );
+ fLog[size] = '\0';
+ fContext->stats_in = fLog;
+ }
+
+ if( avcodec_open( fContext, codec ) < 0 )
+ {
+ Log( "HBMpeg4Encoder: avcodec_open() failed" );
+ fManager->Error();
+ return;
+ }
+
+ fFrame = avcodec_alloc_frame();
+}
+
+void HBMpeg4Encoder::Close()
+{
+ if( fPass == 1 )
+ {
+ fclose( fFile );
+ }
+}
+
+void HBMpeg4Encoder::EncodeBuffer()
+{
+ fFrame->data[0] = fResizedBuffer->fData;
+ fFrame->data[1] = fFrame->data[0] + fTitle->fOutWidth *
+ fTitle->fOutHeight;
+ fFrame->data[2] = fFrame->data[1] + fTitle->fOutWidth *
+ fTitle->fOutHeight / 4;
+ fFrame->linesize[0] = fTitle->fOutWidth;
+ fFrame->linesize[1] = fTitle->fOutWidth / 2;
+ fFrame->linesize[2] = fTitle->fOutWidth / 2;
+
+ HBBuffer * mpeg4Buffer;
+ mpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth *
+ fTitle->fOutHeight / 2 );
+ /* Should be really too much... */
+
+ mpeg4Buffer->fPosition = fResizedBuffer->fPosition;
+ mpeg4Buffer->fSize =
+ avcodec_encode_video( fContext, mpeg4Buffer->fData,
+ mpeg4Buffer->fAllocSize, fFrame );
+ mpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 );
+
+ delete fResizedBuffer;
+
+ if( fPass == 1 )
+ {
+ if( fContext->stats_out )
+ {
+ fprintf( fFile, "%s", fContext->stats_out );
+ }
+ delete mpeg4Buffer;
+ }
+ else
+ {
+ /* Mux it */
+ Push( fTitle->fMpeg4Fifo, mpeg4Buffer );
+ }
+}
+