/* $Id: Mpeg2Decoder.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ #include "Mpeg2Decoder.h" #include "Manager.h" #include "Fifo.h" extern "C" { #include } #include HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitle * title ) : HBThread( "mpeg2decoder" ) { fManager = manager; fTitle = title; } void HBMpeg2Decoder::DoWork() { if( !( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) ) { return; } fPass = fMpeg2Buffer->fPass; Init(); do { while( fSuspend ) { Snooze( 10000 ); } if( fMpeg2Buffer->fPass != fPass ) { Close(); fPass = fMpeg2Buffer->fPass; Init(); } DecodeBuffer(); } while( ( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) ); } void HBMpeg2Decoder::Init() { fLateField = false; /* Init libmpeg2 */ fHandle = mpeg2_init(); } void HBMpeg2Decoder::Close() { /* Close libmpeg2 */ mpeg2_close( fHandle ); } void HBMpeg2Decoder::DecodeBuffer() { const mpeg2_info_t * info = mpeg2_info( fHandle ); /* Feed libmpeg2 */ mpeg2_buffer( fHandle, fMpeg2Buffer->fData, fMpeg2Buffer->fData + fMpeg2Buffer->fSize ); mpeg2_state_t state; for( ;; ) { state = mpeg2_parse( fHandle ); if( state == STATE_BUFFER ) { break; } else if( ( state == STATE_SLICE || state == STATE_END ) && info->display_fbuf ) { HBBuffer * rawBuffer = new HBBuffer( 3 * fTitle->fInWidth * fTitle->fInHeight / 2 ); /* TODO : make libmpeg2 write directly in our buffer */ memcpy( rawBuffer->fData, info->display_fbuf->buf[0], fTitle->fInWidth * fTitle->fInHeight ); memcpy( rawBuffer->fData + fTitle->fInWidth * fTitle->fInHeight, info->display_fbuf->buf[1], fTitle->fInWidth * fTitle->fInHeight / 4 ); memcpy( rawBuffer->fData + fTitle->fInWidth * fTitle->fInHeight + fTitle->fInWidth * fTitle->fInHeight / 4, info->display_fbuf->buf[2], fTitle->fInWidth * fTitle->fInHeight / 4 ); rawBuffer->fPosition = fMpeg2Buffer->fPosition; rawBuffer->fPass = fPass; /* NTSC pulldown kludge */ if( info->display_picture->nb_fields == 3 ) { if( fLateField ) { HBBuffer * buffer = new HBBuffer( rawBuffer->fSize ); buffer->fPosition = rawBuffer->fPosition; buffer->fPass = rawBuffer->fPass; memcpy( buffer->fData, rawBuffer->fData, buffer->fSize ); Push( fTitle->fRawFifo, buffer ); } fLateField = !fLateField; } /* Send it to the encoder */ if( !( Push( fTitle->fRawFifo, rawBuffer ) ) ) { break; } } else if( state == STATE_INVALID ) { /* Shouldn't happen on a DVD */ Log( "HBMpeg2Decoder : STATE_INVALID" ); } } delete fMpeg2Buffer; }