diff options
74 files changed, 6669 insertions, 3640 deletions
@@ -1,33 +1,34 @@ -HandBrake uses a lot of cool libraries from the GNU/Linux world. Thank their authors ! +HandBrake uses a lot of cool libraries from the GNU/Linux world. Thank +their authors ! libdvdcss authors : -Billy Biggs -Stéphane Borel -Håkan Hjort +Billy Biggs +St�phane Borel +H�kan Hjort Samuel Hocevar Eugenio Jarosiewicz Jon Lech Johansen Markus Kuespert Pascal Levesque Steven M. Schultz -David Siebörger +David Sieb�rger Alex Strelnikov German Tischler Gildas Bazin libdvdread authors : -Björn Englund -Hâkan Hjort +Bj�rn Englund +H�kan Hjort Billy Biggs Christian Wolff libdvdplay authors : -Håkan Hjort -Martin Norbäck -Stéphane Borel +H�kan Hjort +Martin Norb�ck +St�phane Borel mpeg2dec authors : @@ -40,7 +41,7 @@ Stephen Crowley Didier Gautheron Ryan C. Gordon Peter Gubanov -Hâkan Hjort +H�kan Hjort Nicolas Joly Gerd Knorr David I. Lehn @@ -64,7 +65,7 @@ Falk Hueffner Zdenek Kabelac Nick Kurshev Michael Niedermayer -François Revol +Fran�ois Revol Dieter Shirley Juan J. Sierralta Lionel Ulmer @@ -76,7 +77,7 @@ Michel Lespinasse Gildas Bazin Billy Biggs Eduard Hasenleithner -Håkan Hjort +H�kan Hjort Charles M. Hannum Chris Hodges Michael Holzt @@ -96,7 +97,7 @@ Alexander Leidinger Naoki Shibata Mark Taylor Takehiro Tominiga -Iván Cavero Belaunde +Iv�n Cavero Belaunde Gabriel Bouvigne Florian Bomers CISC diff --git a/HBAc3Decoder.h b/HBAc3Decoder.h deleted file mode 100644 index f9d6ad678..000000000 --- a/HBAc3Decoder.h +++ /dev/null @@ -1,29 +0,0 @@ -/* $Id: HBAc3Decoder.h,v 1.6 2003/08/25 19:47:14 titer Exp $ */ - -#ifndef HB_AC3_DECODER_H -#define HB_AC3_DECODER_H - -#include "HBThread.h" -class HBAudioInfo; -class HBBuffer; -class HBManager; - -class HBAc3Decoder : public HBThread -{ - public: - HBAc3Decoder( HBManager * manager, HBAudioInfo * audioInfo ); - - private: - void DoWork(); - bool GetBytes( uint32_t size ); - void PushSilence(); - - HBManager * fManager; - HBAudioInfo * fAudioInfo; - - HBBuffer * fAc3Frame; - HBBuffer * fAc3Buffer; - uint32_t fPosInBuffer; -}; - -#endif diff --git a/HBApp.cpp b/HBApp.cpp deleted file mode 100644 index 142b16cb8..000000000 --- a/HBApp.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* $Id: HBApp.cpp,v 1.6 2003/08/24 20:25:49 titer Exp $ */ - -#include "HBCommon.h" -#include "HBApp.h" -#include "HBWindow.h" -#include "HBManager.h" - -/* Constructor */ -HBApp::HBApp() - : BApplication( "application/x-vnd.titer-handbrake" ) -{ - /* Initializations */ - fWindow = new HBWindow(); - fManager = new HBManager( fWindow ); - - /* Tell the interface we now have a manager */ - BMessage * message = new BMessage( MANAGER_CREATED ); - message->AddPointer( "manager", fManager ); - fWindow->PostMessage( message ); - delete message; - - /* Show the main window */ - fWindow->Show(); - - /* Check the available DVDs */ - Status( "Checking DVD volumes...", 0.0, ENABLE_DETECTING ); - fManager->PostMessage( DETECT_VOLUMES ); -} - -void HBApp::MessageReceived( BMessage * message ) -{ - switch( message->what ) - { - case PRINT_MESSAGE: - { - /* See Log() in HBCommon.cpp */ - char * string; - message->FindPointer( "string", (void**) &string ); - fprintf( stderr, string ); - free( string ); - break; - } - - case CHANGE_STATUS: - { - fWindow->PostMessage( message ); - break; - } - - default: - { - BApplication::MessageReceived( message ); - } - } -} - -bool HBApp::QuitRequested() -{ - if( fManager->Cancel() ) - { - /* We have log messages waiting, quit only after having - displayed them */ - PostMessage( B_QUIT_REQUESTED ); - return false; - } - - return true; -} diff --git a/HBApp.h b/HBApp.h deleted file mode 100644 index 0e92a9dee..000000000 --- a/HBApp.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: HBApp.h,v 1.1.1.1 2003/06/24 13:43:48 titer Exp $ */ - -#ifndef _HB_APP_H -#define _HB_APP_H - -#include <Application.h> - -class HBWindow; -class HBManager; - -class HBApp : public BApplication -{ - public: - HBApp(); - virtual void MessageReceived( BMessage * message ); - virtual bool QuitRequested(); - - private: - HBWindow * fWindow; - HBManager * fManager; -}; - -#endif diff --git a/HBAviMuxer.cpp b/HBAviMuxer.cpp deleted file mode 100644 index cbe2f9578..000000000 --- a/HBAviMuxer.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* $Id: HBAviMuxer.cpp,v 1.24 2003/08/26 18:44:06 titer Exp $ */ - -#include "HBCommon.h" -#include "HBAviMuxer.h" -#include "HBManager.h" -#include "HBFifo.h" - -#define AVIF_HASINDEX 0x10 -#define AVIIF_KEYFRAME 0x10 - -HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitleInfo * titleInfo, - HBAudioInfo * audio1Info, HBAudioInfo * audio2Info, - char * fileName ) - : HBThread( "avimuxer" ) -{ - fManager = manager; - fTitleInfo = titleInfo; - fAudio1Info = audio1Info; - fAudio2Info = audio2Info; - fFileName = strdup( fileName ); - - fRiffBytesCount = 2040; - fMoviBytesCount = 4; -} - -void HBAviMuxer::DoWork() -{ - /* Open the destination file */ - if( !( fFile = fopen( fFileName, "w" ) ) ) - { - Log( "HBAviMuxer: fopen failed" ); - fManager->Error(); - return; - } - - /* Initializations */ - memset( &fMainHeader, 0, sizeof( AviMainHeader ) ); - memset( &fVideoStreamHeader, 0, sizeof( AviStreamHeader ) ); - memset( &fAudio1StreamHeader, 0, sizeof( AviStreamHeader ) ); - memset( &fAudio2StreamHeader, 0, sizeof( AviStreamHeader ) ); - memset( &fVideoStreamFormat, 0, sizeof( BitmapInfo ) ); - memset( &fAudio1StreamFormat, 0, sizeof( WaveFormatEx ) ); - memset( &fAudio2StreamFormat, 0, sizeof( WaveFormatEx ) ); - - /* Alloc an 1 MB index (to be realloced later if needed) */ - fIndex = new HBBuffer( 1024 * 1024 ); - sprintf( (char*) fIndex->fData, "idx1" ); - fIndex->fSize = 8; - - /* Main loop */ - int video, audio1, audio2; - while( !fDie ) - { - /* Find the most filled fifo */ - video = fTitleInfo->fMpeg4Fifo->Size(); - audio1 = ( !fAudio1Info->fId ) ? 0 : fAudio1Info->fMp3Fifo->Size(); - audio2 = ( !fAudio2Info->fId ) ? 0 : fAudio2Info->fMp3Fifo->Size(); - - /* Nothing to get - wait a bit and try again */ - if( !video && !audio1 && !audio2 ) - { - snooze( 10000 ); - continue; - } - - /* Got something - mux it */ - if( video >= MAX( audio1, audio2 ) ) - { - AddVideoChunk(); - } - else if( audio1 >= audio2 ) - { - AddAudioChunk( 1 ); - } - else - { - AddAudioChunk( 2 ); - } - } - - /* Write the index */ - uint32_t size = fIndex->fSize - 8; - memcpy( fIndex->fData + 4, &size, 4 ); - fseek( fFile, 0, SEEK_END ); - fwrite( fIndex->fData, fIndex->fSize, 1, fFile ); - - /* Update the headers */ - fRiffBytesCount += fIndex->fSize; - fMainHeader.Flags |= AVIF_HASINDEX; - UpdateMainHeader(); - - delete fIndex; - - fclose( fFile ); -} - -bool HBAviMuxer::AddVideoChunk() -{ - HBBuffer * buffer = fTitleInfo->fMpeg4Fifo->Pop(); - if( !buffer ) - { - return false; - } - - fRiffBytesCount += 8 + EVEN( buffer->fSize ); - fMoviBytesCount += 8 + EVEN( buffer->fSize ); - - fMainHeader.MicroSecPerFrame = 1000000 * (uint64_t) fTitleInfo->fScale / - fTitleInfo->fRate; - fMainHeader.TotalFrames++; - fMainHeader.Width = fTitleInfo->fOutWidth; - fMainHeader.Height = fTitleInfo->fOutHeight; - - fVideoStreamHeader.FourCC = FOURCC( "strh" ); - fVideoStreamHeader.BytesCount = sizeof( AviStreamHeader ) - 8; - fVideoStreamHeader.Type = FOURCC( "vids" ); - fVideoStreamHeader.Handler = FOURCC( "DIVX" ); - fVideoStreamHeader.Scale = fTitleInfo->fScale; - fVideoStreamHeader.Rate = fTitleInfo->fRate; - fVideoStreamHeader.Length++; - - fVideoStreamFormat.FourCC = FOURCC( "strf" ); - fVideoStreamFormat.BytesCount = sizeof( BitmapInfo ) - 8; - fVideoStreamFormat.Size = sizeof( BitmapInfo ) - 8; - fVideoStreamFormat.Width = fTitleInfo->fOutWidth; - fVideoStreamFormat.Height = fTitleInfo->fOutHeight; - fVideoStreamFormat.Planes = 1; - fVideoStreamFormat.BitCount = 24; - fVideoStreamFormat.Compression = FOURCC( "DIVX" );; - - UpdateMainHeader(); - - fseek( fFile, 0, SEEK_END ); - - /* Update the index */ - if( fIndex->fSize + 16 > fIndex->fAllocSize ) - { - /* Realloc if needed */ - Log( "HBAviMuxer::AddVideoChunk() : reallocing index (%d -> %d MB)", - fIndex->fAllocSize / ( 1024 * 1024 ), - 1 + fIndex->fAllocSize / ( 1024 * 1024 ) ); - fIndex->ReAlloc( fIndex->fAllocSize + 1024 * 1024 ); - } - - uint32_t flags = buffer->fKeyFrame ? AVIIF_KEYFRAME : 0; - uint32_t offset = ftell( fFile ) - 2044; - sprintf( (char*)fIndex->fData + fIndex->fSize, "00dc" ); - - memcpy( fIndex->fData + fIndex->fSize + 4, &flags, 4 ); - memcpy( fIndex->fData + fIndex->fSize + 8, &offset, 4 ); - memcpy( fIndex->fData + fIndex->fSize + 12, &buffer->fSize, 4 ); - fIndex->fSize += 16; - - /* Write the chunk */ - fwrite( "00dc", 4, 1, fFile ); - fwrite( &buffer->fSize, 4, 1, fFile ); - fwrite( buffer->fData, buffer->fSize, 1, fFile ); - - /* Chunks must be 2-bytes aligned */ - if( buffer->fSize & 1 ) - { - fputc( 0, fFile ); - } - - delete buffer; - - return true; -} - -bool HBAviMuxer::AddAudioChunk( int which ) -{ - HBAudioInfo * info; - AviStreamHeader * streamHeader; - WaveFormatEx * streamFormat; - - if( which == 1 ) - { - info = fAudio1Info; - streamHeader = &fAudio1StreamHeader; - streamFormat = &fAudio1StreamFormat; - } - else - { - info = fAudio2Info; - streamHeader = &fAudio2StreamHeader; - streamFormat = &fAudio2StreamFormat; - } - - HBBuffer * buffer = info->fMp3Fifo->Pop(); - if( !buffer ) - { - return false; - } - - fRiffBytesCount += 8 + EVEN( buffer->fSize ); - fMoviBytesCount += 8 + EVEN( buffer->fSize ); - - streamHeader->FourCC = FOURCC( "strh" ); - streamHeader->BytesCount = sizeof( AviStreamHeader ) - 8; - streamHeader->Type = FOURCC( "auds" ); - streamHeader->InitialFrames = 1; - streamHeader->Scale = 1152; - streamHeader->Rate = info->fOutSampleRate; - streamHeader->Length++; - streamHeader->Quality = 0xFFFFFFFF; - - - streamFormat->FourCC = FOURCC( "strf" ); - streamFormat->BytesCount = sizeof( WaveFormatEx ) - 8; - streamFormat->FormatTag = 0x55; - streamFormat->Channels = 2; - streamFormat->SamplesPerSec = info->fOutSampleRate; - streamFormat->AvgBytesPerSec = info->fOutBitrate * 1024 / 8; - streamFormat->BlockAlign = 1152; - - /* stolen from libavformat/wav.c */ - streamFormat->Size = 12; - streamFormat->Id = 1; - streamFormat->Flags = 2; - streamFormat->BlockSize = 1152; - streamFormat->FramesPerBlock = 1; - streamFormat->CodecDelay = 1393; - - UpdateMainHeader(); - - fseek( fFile, 0, SEEK_END ); - - /* Update the index */ - if( fIndex->fSize + 16 > fIndex->fAllocSize ) - { - /* Realloc if needed */ - Log( "HBAviMuxer::AddAudioChunk() : reallocing index (%d -> %d MB)", - fIndex->fAllocSize / ( 1024 * 1024 ), - 1 + fIndex->fAllocSize / ( 1024 * 1024 ) ); - fIndex->ReAlloc( fIndex->fAllocSize + 1024 * 1024 ); - } - - uint32_t flags = buffer->fKeyFrame ? AVIIF_KEYFRAME : 0; - uint32_t offset = ftell( fFile ) - 2044; - sprintf( (char*)fIndex->fData + fIndex->fSize, "%02dwb", which ); - - memcpy( fIndex->fData + fIndex->fSize + 4, &flags, 4 ); - memcpy( fIndex->fData + fIndex->fSize + 8, &offset, 4 ); - memcpy( fIndex->fData + fIndex->fSize + 12, &buffer->fSize, 4 ); - fIndex->fSize += 16; - - /* Write the chunk */ - fprintf( fFile, "%02dwb", which ); - fwrite( &buffer->fSize, 4, 1, fFile ); - fwrite( buffer->fData, buffer->fSize, 1, fFile ); - - /* Chunks must be 2-bytes aligned */ - if( buffer->fSize & 1 ) - { - fputc( 0, fFile ); - } - - delete buffer; - - return true; -} - -void HBAviMuxer::UpdateMainHeader() -{ - fMainHeader.FourCC = FOURCC( "avih" ); - fMainHeader.BytesCount = sizeof( AviMainHeader ) - 8; - fMainHeader.Streams = 2; - - fHdrlBytesCount = 4 + sizeof( AviMainHeader ) - + 12 + sizeof( AviStreamHeader ) + sizeof( BitmapInfo ); - - if( fAudio1Info->fId ) - { - fHdrlBytesCount += 12 + sizeof( AviStreamHeader ) + sizeof( WaveFormatEx ); - } - if( fAudio2Info->fId ) - { - fHdrlBytesCount += 12 + sizeof( AviStreamHeader ) + sizeof( WaveFormatEx ); - } - - fseek( fFile, 0, SEEK_SET ); - fwrite( "RIFF", 4, 1, fFile ); - fwrite( &fRiffBytesCount, 4, 1, fFile ); - fwrite( "AVI ", 4, 1, fFile ); - fwrite( "LIST", 4, 1, fFile ); - fwrite( &fHdrlBytesCount, 4, 1, fFile ); - fwrite( "hdrl", 4, 1, fFile ); - - fwrite( &fMainHeader, sizeof( AviMainHeader ), 1, fFile ); - - int strlSize; - strlSize = 4 + sizeof( AviStreamHeader ) + sizeof( BitmapInfo ); - fwrite( "LIST", 4, 1, fFile ); - fwrite( &strlSize, 4, 1, fFile ); - fwrite( "strl", 4, 1, fFile ); - fwrite( &fVideoStreamHeader, sizeof( AviStreamHeader ), 1, fFile ); - fwrite( &fVideoStreamFormat, sizeof( fVideoStreamFormat ), 1, fFile ); - - if( fAudio1Info->fId ) - { - strlSize = 4 + sizeof( AviStreamHeader ) + sizeof( WaveFormatEx ); - fwrite( "LIST", 4, 1, fFile ); - fwrite( &strlSize, 4, 1, fFile ); - fwrite( "strl", 4, 1, fFile ); - fwrite( &fAudio1StreamHeader, sizeof( AviStreamHeader ), 1, fFile ); - fwrite( &fAudio1StreamFormat, sizeof( WaveFormatEx ), 1, fFile ); - } - - if( fAudio2Info->fId ) - { - strlSize = 4 + sizeof( AviStreamHeader ) + sizeof( WaveFormatEx ); - fwrite( "LIST", 4, 1, fFile ); - fwrite( &strlSize, 4, 1, fFile ); - fwrite( "strl", 4, 1, fFile ); - fwrite( &fAudio2StreamHeader, sizeof( AviStreamHeader ), 1, fFile ); - fwrite( &fAudio2StreamFormat, sizeof( WaveFormatEx ), 1, fFile ); - } - - /* a JUNK chunk to fill the free space. - size = 2048 -/ - 12 ("RIFFxxxxAVI ") - - 8 (hdrl's "LIS1Txxxx") - - fHdrlBytesCount - - 8 ("JUNKxxxx") - - 12 ("LISTxxxxmovi) */ - int junkSize = 2008 - fHdrlBytesCount; - fwrite( "JUNK", 4, 1, fFile ); - fwrite( &junkSize, 4, 1, fFile ); - for( uint32_t i = 0; i < 2008 - fHdrlBytesCount; i++ ) - { - fputc( 0, fFile ); - } - - /* movi list */ - fwrite( "LIST", 4, 1, fFile ); - fwrite( &fMoviBytesCount, 4, 1, fFile ); - fwrite( "movi", 4, 1, fFile ); -} diff --git a/HBAviMuxer.h b/HBAviMuxer.h deleted file mode 100644 index 55c2dc248..000000000 --- a/HBAviMuxer.h +++ /dev/null @@ -1,149 +0,0 @@ -/* $Id: HBAviMuxer.h,v 1.8 2003/08/23 16:20:59 titer Exp $ */ - -#ifndef HB_AVI_MUXER_H -#define HB_AVI_MUXER_H - -#include "HBThread.h" -class HBManager; -class HBFifo; -class HBBuffer; -class HBAudioInfo; -class HBTitleInfo; - -#define FOURCC(a) \ - ( ( a[3] << 24 ) | ( a[2] << 16 ) | ( a[1] << 8 ) | a[0] ) - -/* Misc structures used in AVI headers */ -typedef struct __attribute__((__packed__)) BitmapInfo -{ - uint32_t FourCC; - uint32_t BytesCount; - uint32_t Size; - uint32_t Width; - uint32_t Height; - uint16_t Planes; - uint16_t BitCount; - uint32_t Compression; - uint32_t SizeImage; - uint32_t XPelsPerMeter; - uint32_t YPelsPerMeter; - uint32_t ClrUsed; - uint32_t ClrImportant; - uint8_t Blue; - uint8_t Green; - uint8_t Red; - uint8_t Reserved; -} BitmapInfo; - -typedef struct __attribute__((__packed__)) WaveFormatEx -{ - uint32_t FourCC; - uint32_t BytesCount; - uint16_t FormatTag; - uint16_t Channels; - uint32_t SamplesPerSec; - uint32_t AvgBytesPerSec; - uint16_t BlockAlign; - uint16_t BitsPerSample; - uint16_t Size; - - /* mp3 specific */ - uint16_t Id; - uint32_t Flags; - uint16_t BlockSize; - uint16_t FramesPerBlock; - uint16_t CodecDelay; -} WaveFormatEx; - -typedef struct __attribute__((__packed__)) AviStreamHeader -{ - uint32_t FourCC; - uint32_t BytesCount; - uint32_t Type; - uint32_t Handler; - uint32_t Flags; - uint16_t Priority; - uint16_t Language; - uint32_t InitialFrames; - uint32_t Scale; - uint32_t Rate; - uint32_t Start; - uint32_t Length; - uint32_t SuggestedBufferSize; - uint32_t Quality; - uint32_t SampleSize; - int16_t Left; - int16_t Top; - int16_t Right; - int16_t Bottom; -} AviStreamHeader; - -typedef struct __attribute__((__packed__)) AviMainHeader -{ - uint32_t FourCC; - uint32_t BytesCount; - uint32_t MicroSecPerFrame; - uint32_t MaxBytesPerSec; - uint32_t PaddingGranularity; - uint32_t Flags; - uint32_t TotalFrames; - uint32_t InitialFrames; - uint32_t Streams; - uint32_t SuggestedBufferSize; - uint32_t Width; - uint32_t Height; - uint32_t Reserved[4]; -} AviMainHeader; - -typedef struct AviOldIndexEntry -{ - char StreamNb[2]; - char Code[2]; - uint32_t Flags; - uint32_t Offset; - uint32_t Size; -} AviOldIndexEntry; - -class HBAviMuxer : public HBThread -{ - public: - HBAviMuxer( HBManager * manager, HBTitleInfo * titleInfo, - HBAudioInfo * audio1Info, HBAudioInfo * audio2Info, - char * fileName ); - - private: - void DoWork(); - bool AddVideoChunk(); - bool AddAudioChunk( int which ); - void UpdateMainHeader(); - - HBManager * fManager; - HBTitleInfo * fTitleInfo; - HBAudioInfo * fAudio1Info; - HBAudioInfo * fAudio2Info; - char * fFileName; - - FILE * fFile; - - /* The main header */ - AviMainHeader fMainHeader; - - /* The video track */ - AviStreamHeader fVideoStreamHeader; - BitmapInfo fVideoStreamFormat; - - /* The audio tracks */ - AviStreamHeader fAudio1StreamHeader; - WaveFormatEx fAudio1StreamFormat; - AviStreamHeader fAudio2StreamHeader; - WaveFormatEx fAudio2StreamFormat; - - uint32_t fRiffBytesCount; - uint32_t fHdrlBytesCount; - uint32_t fMoviBytesCount; - - HBBuffer * fIndex; - -}; - -#endif diff --git a/HBCommon.cpp b/HBCommon.cpp deleted file mode 100644 index 9a88cb529..000000000 --- a/HBCommon.cpp +++ /dev/null @@ -1,567 +0,0 @@ -/* $Id: HBCommon.cpp,v 1.6 2003/08/24 21:56:03 titer Exp $ */ - -#include "HBCommon.h" -#include "HBFifo.h" -#include "HBMpegDemux.h" -#include "HBPictureWin.h" -#include "HBWindow.h" - -#include <Application.h> - -#include <dvdread/ifo_types.h> -#include <dvdplay/dvdplay.h> -#include <dvdplay/info.h> -#include <dvdplay/state.h> -#include <dvdplay/nav.h> - -extern "C" { -#include <mpeg2dec/mpeg2.h> -} - -void Log( char * log, ... ) -{ - char * string = (char*) malloc( 1024 ); - - /* Show the time */ - time_t _now = time( NULL ); - struct tm * now = localtime( &_now ); - sprintf( string, "[%02d:%02d:%02d] ", - now->tm_hour, now->tm_min, now->tm_sec ); - - /* Convert the message to a string */ - va_list args; - va_start( args, log ); - int ret = vsnprintf( string + 11, 1011, log, args ); - va_end( args ); - - /* Add the end of line */ - string[ret+11] = '\n'; - string[ret+12] = '\0'; - - /* Send this to the be_app */ - /* We do this so we are sure that only one message is printed - at a time */ - BMessage * message = new BMessage( PRINT_MESSAGE ); - message->AddPointer( "string", string ); - be_app->PostMessage( message ); - delete message; -} - -void Status( char * text, float pos, int mode ) -{ - char * textCopy = strdup( text ); - BMessage * message = new BMessage( CHANGE_STATUS ); - message->AddPointer( "text", textCopy ); - message->AddFloat( "pos", pos ); - message->AddInt32( "mode", mode ); - be_app->PostMessage( message ); - delete message; -} - -/* Get a readable language description from the code */ -iso639_lang_t languages[] = -{ { "Afar", "", "aa" }, - { "Abkhazian", "", "ab" }, - { "Afrikaans", "", "af" }, - { "Albanian", "", "sq" }, - { "Amharic", "", "am" }, - { "Arabic", "", "ar" }, - { "Armenian", "", "hy" }, - { "Assamese", "", "as" }, - { "Avestan", "", "ae" }, - { "Aymara", "", "ay" }, - { "Azerbaijani", "", "az" }, - { "Bashkir", "", "ba" }, - { "Basque", "", "eu" }, - { "Belarusian", "", "be" }, - { "Bengali", "", "bn" }, - { "Bihari", "", "bh" }, - { "Bislama", "", "bi" }, - { "Bosnian", "", "bs" }, - { "Breton", "", "br" }, - { "Bulgarian", "", "bg" }, - { "Burmese", "", "my" }, - { "Catalan", "", "ca" }, - { "Chamorro", "", "ch" }, - { "Chechen", "", "ce" }, - { "Chinese", "", "zh" }, - { "Church Slavic", "", "cu" }, - { "Chuvash", "", "cv" }, - { "Cornish", "", "kw" }, - { "Corsican", "", "co" }, - { "Czech", "", "cs" }, - { "Danish", "Dansk", "da" }, - { "Dutch", "Nederlands", "nl" }, - { "Dzongkha", "", "dz" }, - { "English", "English", "en" }, - { "Esperanto", "", "eo" }, - { "Estonian", "", "et" }, - { "Faroese", "", "fo" }, - { "Fijian", "", "fj" }, - { "Finnish", "Suomi", "fi" }, - { "French", "Francais", "fr" }, - { "Frisian", "", "fy" }, - { "Georgian", "", "ka" }, - { "German", "Deutsch", "de" }, - { "Gaelic (Scots)", "", "gd" }, - { "Irish", "", "ga" }, - { "Gallegan", "", "gl" }, - { "Manx", "", "gv" }, - { "Greek, Modern ()", "", "el" }, - { "Guarani", "", "gn" }, - { "Gujarati", "", "gu" }, - { "Hebrew", "", "he" }, - { "Herero", "", "hz" }, - { "Hindi", "", "hi" }, - { "Hiri Motu", "", "ho" }, - { "Hungarian", "Magyar", "hu" }, - { "Icelandic", "Islenska", "is" }, - { "Inuktitut", "", "iu" }, - { "Interlingue", "", "ie" }, - { "Interlingua", "", "ia" }, - { "Indonesian", "", "id" }, - { "Inupiaq", "", "ik" }, - { "Italian", "Italiano", "it" }, - { "Javanese", "", "jv" }, - { "Japanese", "", "ja" }, - { "Kalaallisut (Greenlandic)", "", "kl" }, - { "Kannada", "", "kn" }, - { "Kashmiri", "", "ks" }, - { "Kazakh", "", "kk" }, - { "Khmer", "", "km" }, - { "Kikuyu", "", "ki" }, - { "Kinyarwanda", "", "rw" }, - { "Kirghiz", "", "ky" }, - { "Komi", "", "kv" }, - { "Korean", "", "ko" }, - { "Kuanyama", "", "kj" }, - { "Kurdish", "", "ku" }, - { "Lao", "", "lo" }, - { "Latin", "", "la" }, - { "Latvian", "", "lv" }, - { "Lingala", "", "ln" }, - { "Lithuanian", "", "lt" }, - { "Letzeburgesch", "", "lb" }, - { "Macedonian", "", "mk" }, - { "Marshall", "", "mh" }, - { "Malayalam", "", "ml" }, - { "Maori", "", "mi" }, - { "Marathi", "", "mr" }, - { "Malay", "", "ms" }, - { "Malagasy", "", "mg" }, - { "Maltese", "", "mt" }, - { "Moldavian", "", "mo" }, - { "Mongolian", "", "mn" }, - { "Nauru", "", "na" }, - { "Navajo", "", "nv" }, - { "Ndebele, South", "", "nr" }, - { "Ndebele, North", "", "nd" }, - { "Ndonga", "", "ng" }, - { "Nepali", "", "ne" }, - { "Norwegian", "Norsk", "no" }, - { "Norwegian Nynorsk", "", "nn" }, - { "Norwegian Bokmål", "", "nb" }, - { "Chichewa; Nyanja", "", "ny" }, - { "Occitan (post 1500); Provençal", "", "oc" }, - { "Oriya", "", "or" }, - { "Oromo", "", "om" }, - { "Ossetian; Ossetic", "", "os" }, - { "Panjabi", "", "pa" }, - { "Persian", "", "fa" }, - { "Pali", "", "pi" }, - { "Polish", "", "pl" }, - { "Portuguese", "Portugues", "pt" }, - { "Pushto", "", "ps" }, - { "Quechua", "", "qu" }, - { "Raeto-Romance", "", "rm" }, - { "Romanian", "", "ro" }, - { "Rundi", "", "rn" }, - { "Russian", "", "ru" }, - { "Sango", "", "sg" }, - { "Sanskrit", "", "sa" }, - { "Serbian", "", "sr" }, - { "Croatian", "Hrvatski", "hr" }, - { "Sinhalese", "", "si" }, - { "Slovak", "", "sk" }, - { "Slovenian", "", "sl" }, - { "Northern Sami", "", "se" }, - { "Samoan", "", "sm" }, - { "Shona", "", "sn" }, - { "Sindhi", "", "sd" }, - { "Somali", "", "so" }, - { "Sotho, Southern", "", "st" }, - { "Spanish", "Espanol", "es" }, - { "Sardinian", "", "sc" }, - { "Swati", "", "ss" }, - { "Sundanese", "", "su" }, - { "Swahili", "", "sw" }, - { "Swedish", "Svenska", "sv" }, - { "Tahitian", "", "ty" }, - { "Tamil", "", "ta" }, - { "Tatar", "", "tt" }, - { "Telugu", "", "te" }, - { "Tajik", "", "tg" }, - { "Tagalog", "", "tl" }, - { "Thai", "", "th" }, - { "Tibetan", "", "bo" }, - { "Tigrinya", "", "ti" }, - { "Tonga (Tonga Islands)", "", "to" }, - { "Tswana", "", "tn" }, - { "Tsonga", "", "ts" }, - { "Turkish", "", "tr" }, - { "Turkmen", "", "tk" }, - { "Twi", "", "tw" }, - { "Uighur", "", "ug" }, - { "Ukrainian", "", "uk" }, - { "Urdu", "", "ur" }, - { "Uzbek", "", "uz" }, - { "Vietnamese", "", "vi" }, - { "Volapük", "", "vo" }, - { "Welsh", "", "cy" }, - { "Wolof", "", "wo" }, - { "Xhosa", "", "xh" }, - { "Yiddish", "", "yi" }, - { "Yoruba", "", "yo" }, - { "Zhuang", "", "za" }, - { "Zulu", "", "zu" }, - { NULL, NULL, NULL } }; - -char * LanguageForCode( int code ) -{ - char codeString[2]; - codeString[0] = ( code >> 8 ) & 0xFF; - codeString[1] = code & 0xFF; - - iso639_lang_t * lang; - for( lang = languages; lang->engName; lang++ ) - { - if( !strncmp( lang->iso639_1, codeString, 2 ) ) - { - if( *lang->nativeName ) - return lang->nativeName; - - return lang->engName; - } - } - - return "Unknown"; -} - -HBVolumeInfo::HBVolumeInfo( char * name, char * device ) - : BMenuItem( "", new BMessage( VOLUME_SELECTED ) ) -{ - fInitOK = false; - fName = strdup( name ); - fDevice = strdup( device ); - fTitleList = new BList(); - - SetLabel( fName ); - - /* Open the device */ - dvdplay_ptr vmg; - vmg = dvdplay_open( device, NULL, NULL ); - if( !vmg ) - { - Log( "VolumeInfo::DetectTitles: dvdplay_open() failed (%s)", - device ); - return; - } - - /* Detect titles */ - HBTitleInfo * titleInfo; - for( int i = 0; i < dvdplay_title_nr( vmg ); i++ ) - { - Log( "HBVolumeInfo : new title (%d)", i + 1 ); - - char statusText[128]; memset( statusText, 0, 128 ); - snprintf( statusText, 128, - "Checking DVD volumes (%s, title %d)...", - fName, i + 1 ); - Status( statusText, 0.0, ENABLE_DETECTING ); - - titleInfo = new HBTitleInfo( vmg, i + 1, device ); - - if( !titleInfo->InitCheck() ) - { - delete titleInfo; - continue; - } - - fTitleList->AddItem( titleInfo ); - } - - dvdplay_close( vmg ); - - if( fTitleList->CountItems() > 0 ) - { - fInitOK = true; - } - -} - -HBVolumeInfo::~HBVolumeInfo() -{ - free( fName ); - free( fDevice ); - - HBTitleInfo * titleInfo; - while( ( titleInfo = (HBTitleInfo*) fTitleList->ItemAt( 0 ) ) ) - { - fTitleList->RemoveItem( titleInfo ); - delete titleInfo; - } - delete fTitleList; -} - -bool HBVolumeInfo::InitCheck() -{ - return fInitOK; -} - -HBTitleInfo::HBTitleInfo( dvdplay_ptr vmg, int index, char * device ) - : BMenuItem( "", new BMessage( TITLE_SELECTED ) ) -{ - fInitOK = false; - fDevice = strdup( device ); - fIndex = index; - - fAudioInfoList1 = new BList(); - fAudioInfoList2 = new BList(); - fPSFifo = NULL; - fMpeg2Fifo = NULL; - fRawFifo = NULL; - fMpeg4Fifo = NULL; - - dvdplay_start( vmg, fIndex ); - - /* Length */ - fLength = dvdplay_title_time( vmg ); - - /* Discard titles under 60 seconds */ - if( fLength < 60 ) - { - Log( "HBTitleInfo : skipping title %d (length = %lld sec)", - index, fLength ); - return; - } - - char label[1024]; memset( label, 0, 1024 ); - sprintf( label, "Title %d (%02lld:%02lld:%02lld)", - index, fLength / 3600, ( fLength % 3600 ) / 60, - fLength % 60 ); - SetLabel( label ); - - /* Detect languages */ - int audio_nr, audio; - dvdplay_audio_info( vmg, &audio_nr, &audio ); - - audio_attr_t * attr; - HBAudioInfo * audioInfo; - for( int i = 0; i < audio_nr; i++ ) - { - int id = dvdplay_audio_id( vmg, i ); - if( id > 0 ) - { - Log( "HBTitleInfo : new language (%x)", id ); - attr = dvdplay_audio_attr( vmg, i ); - audioInfo = new HBAudioInfo( id, LanguageForCode( attr->lang_code ) ); - fAudioInfoList1->AddItem( audioInfo ); - } - } - - /* Discard titles with no audio tracks */ - if( !fAudioInfoList1->CountItems() ) - { - Log( "HBTitleInfo : skipping title %d (no audio track)", index ); - return; - } - - /* Add a dummy 'None' language */ - audioInfo = new HBAudioInfo( 0, "None" ); - fAudioInfoList1->AddItem( audioInfo ); - - /* Duplicate the audio list */ - for( int i = 0; i < fAudioInfoList1->CountItems(); i++ ) - { - audioInfo = (HBAudioInfo*) fAudioInfoList1->ItemAt( i ); - fAudioInfoList2->AddItem( new HBAudioInfo( audioInfo ) ); - } - - /* Decode a few pictures so the user can crop/resize it */ - int titleFirst = dvdplay_title_first ( vmg ); - int titleEnd = dvdplay_title_end( vmg ); - - /* Kludge : libdvdplay wants we to read a first block before seeking */ - uint8_t dummyBuf[2048]; - dvdplay_read( vmg, dummyBuf, 1 ); - - for( int i = 0; i < 10; i++ ) - { - dvdplay_seek( vmg, ( i + 1 ) * ( titleEnd - titleFirst ) / 11 ) ; - if( !DecodeFrame( vmg, i ) ) - { - Log( "HBTitleInfo::HBTitleInfo : could not decode frame %d", i ); - return; - } - } - - fPictureWin = new HBPictureWin( this ); - - fInitOK = true; -} - -HBTitleInfo::~HBTitleInfo() -{ - HBAudioInfo * audioInfo; - - while( ( audioInfo = (HBAudioInfo*) fAudioInfoList1->ItemAt( 0 ) ) ) - { - fAudioInfoList1->RemoveItem( audioInfo ); - delete audioInfo; - } - delete fAudioInfoList1; - - while( ( audioInfo = (HBAudioInfo*) fAudioInfoList2->ItemAt( 0 ) ) ) - { - fAudioInfoList2->RemoveItem( audioInfo ); - delete audioInfo; - } - delete fAudioInfoList2; -} - -bool HBTitleInfo::DecodeFrame( dvdplay_ptr vmg, int i ) -{ - /* Init libmpeg2 */ - mpeg2dec_t * handle = mpeg2_init(); - const mpeg2_info_t * info = mpeg2_info( handle ); - mpeg2_state_t state; - - BList * esBufferList = NULL; - HBBuffer * psBuffer = NULL; - HBBuffer * esBuffer = NULL; - - for( ;; ) - { - state = mpeg2_parse( handle ); - - if( state == STATE_BUFFER ) - { - /* Free the previous buffer */ - if( esBuffer ) - { - delete esBuffer; - esBuffer = NULL; - } - - /* Get a new one */ - while( !esBuffer ) - { - while( !esBufferList ) - { - psBuffer = new HBBuffer( DVD_VIDEO_LB_LEN ); - if( dvdplay_read( vmg, psBuffer->fData, 1 ) != 1 ) - { - Log( "dvdplay_read failed" ); - } - esBufferList = PStoES( psBuffer ); - } - - esBuffer = (HBBuffer*) esBufferList->ItemAt( 0 ); - esBufferList->RemoveItem( esBuffer ); - if( !esBufferList->CountItems() ) - { - delete esBufferList; - esBufferList = NULL; - } - - if( esBuffer->fStreamId != 0xE0 ) - { - delete esBuffer; - esBuffer = NULL; - } - } - - /* Feed libmpeg2 */ - mpeg2_buffer( handle, esBuffer->fData, - esBuffer->fData + esBuffer->fSize ); - } - else if( state == STATE_SEQUENCE ) - { - /* Get size & framerate info */ - fInWidth = info->sequence->width; - fInHeight = info->sequence->height; - fPixelWidth = info->sequence->pixel_width; - fPixelHeight = info->sequence->pixel_height; - fPictures[i] = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 ); - fRate = 27000000; - fScale = info->sequence->frame_period; - } - else if( ( state == STATE_SLICE || state == STATE_END ) && - ( info->display_fbuf ) && - ( info->display_picture->flags & PIC_MASK_CODING_TYPE ) - == PIC_FLAG_CODING_TYPE_I ) - { - /* Copy it */ - /* TODO : make libmpeg2 write directly in our buffer */ - memcpy( fPictures[i], - info->display_fbuf->buf[0], - fInWidth * fInHeight ); - memcpy( fPictures[i] + fInWidth * fInHeight, - info->display_fbuf->buf[1], - fInWidth * fInHeight / 4 ); - memcpy( fPictures[i] + 5 * fInWidth * fInHeight / 4, - info->display_fbuf->buf[2], - fInWidth * fInHeight / 4 ); - break; - } - else if( state == STATE_INVALID ) - { - /* Reset libmpeg2 */ - mpeg2_close( handle ); - handle = mpeg2_init(); - } - } - - mpeg2_close( handle ); - - return true; -} - -bool HBTitleInfo::InitCheck() -{ - return fInitOK; -} - -/* Audio track */ -HBAudioInfo::HBAudioInfo( int id, char * description ) - : BMenuItem( "", new BMessage( LANGUAGE_SELECTED ) ) -{ - fId = id; - fOutSampleRate = 44100; - - fAc3Fifo = NULL; - fRawFifo = NULL; - fMp3Fifo = NULL; - - SetLabel( description ); -} - -HBAudioInfo::HBAudioInfo( HBAudioInfo * audioInfo ) - : BMenuItem( "", new BMessage( LANGUAGE_SELECTED ) ) -{ - fId = audioInfo->fId; - fInSampleRate = audioInfo->fInSampleRate; - fOutSampleRate = audioInfo->fOutSampleRate; - fInBitrate = audioInfo->fInBitrate; - fOutBitrate = audioInfo->fOutBitrate; - - fAc3Fifo = NULL; - fRawFifo = NULL; - fMp3Fifo = NULL; - - SetLabel( audioInfo->Label() ); -} - -HBAudioInfo::~HBAudioInfo() -{ -} diff --git a/HBCommon.h b/HBCommon.h deleted file mode 100644 index 3e84c3dc5..000000000 --- a/HBCommon.h +++ /dev/null @@ -1,146 +0,0 @@ -/* $Id: HBCommon.h,v 1.9 2003/08/24 19:28:18 titer Exp $ */ - -#ifndef _HB_COMMON_H -#define _HB_COMMON_H - -/* standard headers */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <inttypes.h> -typedef uint8_t byte_t; - -/* BeOS headers */ -#include <Looper.h> -#include <MenuItem.h> - -/* Internal headers */ -class HBFifo; -class HBPictureWin; - -/* Misc structures */ -typedef struct dvdplay_s * dvdplay_ptr; -typedef struct iso639_lang_t -{ - char * engName; /* Description in English */ - char * nativeName; /* Description in native language */ - char * iso639_1; /* ISO-639-1 (2 characters) code */ -} iso639_lang_t; - -/* BMessages */ -#define MANAGER_CREATED 'macr' -#define PRINT_MESSAGE 'prme' -#define DETECT_VOLUMES 'devo' -#define START_CONVERT 'stac' -#define STOP_CONVERT 'stoc' -#define SUSPEND_CONVERT 'suco' -#define RESUME_CONVERT 'reco' -#define VOLUMES_DETECTED 'vode' -#define REFRESH_VOLUMES 'revo' -#define VIDEO_SLIDER 'visl' -#define AUDIO_SLIDER 'ausl' -#define PICTURE_WIN 'piwi' -#define NOT_IMPLEMENTED 'noim' -#define VOLUME_SELECTED 'vose' -#define TITLE_SELECTED 'tise' -#define LANGUAGE_SELECTED 'lase' -#define CHANGE_STATUS 'chst' - -/* Handy macros */ -#define EVEN( a ) ( ( (a) & 0x1 ) ? ( (a) + 1 ) : (a) ) -#define MULTIPLE_16( a ) ( ( ( (a) % 16 ) < 8 ) ? ( (a) - ( (a) % 16 ) ) \ - : ( (a) - ( (a) % 16 ) + 16 ) ) - -/* Global prototypes */ -void Log( char * log, ... ); -void Status( char * text, float pos, int mode ); -char * LanguageForCode( int code ); - -/* Possible modes in Status() */ -#define ENABLE_DETECTING 0x1 -#define ENABLE_READY 0x2 -#define ENABLE_ENCODING 0x4 - -/* Classes */ - -class HBAudioInfo : public BMenuItem -{ - public: - /* Common methods and members */ - HBAudioInfo( int id, char * description ); - HBAudioInfo( HBAudioInfo * audioInfo ); - ~HBAudioInfo(); - - uint32_t fId; - HBFifo * fAc3Fifo; - HBFifo * fRawFifo; - HBFifo * fMp3Fifo; - - int fInSampleRate; - int fOutSampleRate; - int fInBitrate; - int fOutBitrate; -}; - -class HBTitleInfo : public BMenuItem -{ - public: - HBTitleInfo( dvdplay_ptr vmg, int index, char * device ); - ~HBTitleInfo(); - bool InitCheck(); - - bool fInitOK; - char * fDevice; - int fIndex; - uint64_t fLength; - - /* MPEG2-PS data */ - HBFifo * fPSFifo; - - /* Video info */ - bool DecodeFrame( dvdplay_ptr vmg, int i ); - - HBFifo * fMpeg2Fifo; - HBFifo * fRawFifo; - HBFifo * fMpeg4Fifo; - - /* Video input */ - uint32_t fInWidth; - uint32_t fInHeight; - uint32_t fPixelWidth; - uint32_t fPixelHeight; - uint32_t fRate; - uint32_t fScale; - - /* Video output */ - bool fDeinterlace; - uint32_t fOutWidth; - uint32_t fOutHeight; - uint32_t fTopCrop; - uint32_t fBottomCrop; - uint32_t fLeftCrop; - uint32_t fRightCrop; - uint32_t fBitrate; - - uint8_t * fPictures[10]; - HBPictureWin * fPictureWin; - - /* Audio infos */ - BList * fAudioInfoList1; - BList * fAudioInfoList2; -}; - -class HBVolumeInfo : public BMenuItem -{ - public: - HBVolumeInfo( char * name, char * device ); - ~HBVolumeInfo(); - bool InitCheck(); - - bool fInitOK; - char * fName; - char * fDevice; - BList * fTitleList; -}; - -#endif diff --git a/HBDVDReader.cpp b/HBDVDReader.cpp deleted file mode 100644 index 2027da7e6..000000000 --- a/HBDVDReader.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* $Id: HBDVDReader.cpp,v 1.7 2003/08/12 20:10:50 titer Exp $ */ - -#include "HBCommon.h" -#include "HBDVDReader.h" -#include "HBManager.h" -#include "HBFifo.h" - -#include <Application.h> - -#include <dvdread/ifo_types.h> -#include <dvdplay/dvdplay.h> -#include <dvdplay/info.h> -#include <dvdplay/state.h> -#include <dvdplay/nav.h> - -HBDVDReader::HBDVDReader( HBManager * manager, - HBTitleInfo * titleInfo ) - : HBThread( "dvdreader", B_NORMAL_PRIORITY ) -{ - fManager = manager; - fTitleInfo = titleInfo; -} - -void HBDVDReader::DoWork() -{ - /* Open the device */ - dvdplay_ptr vmg; - vmg = dvdplay_open( fTitleInfo->fDevice, NULL, NULL ); - if( !vmg ) - { - Log( "HBDVDReader: dvdplay_open() failed" ); - fManager->Error(); - return; - } - - /* Open the title */ - dvdplay_start( vmg, fTitleInfo->fIndex ); - - /* Read */ - HBBuffer * dvdBuffer; - int beginPosition = dvdplay_position( vmg ); - int endPosition = dvdplay_title_end( vmg ); - while( dvdplay_position( vmg ) < endPosition ) - { - dvdBuffer = new HBBuffer( DVD_VIDEO_LB_LEN ); - dvdBuffer->fPosition = (float) ( dvdplay_position( vmg ) - beginPosition ) / - (float) ( endPosition - beginPosition ) ; - - if( dvdplay_read( vmg, dvdBuffer->fData, 1 ) < 0 ) - { - Log( "HBDVDReader: could not dvdplay_read()" ); - delete dvdBuffer; - fManager->Error(); - break; - } - if( !( fTitleInfo->fPSFifo->Push( dvdBuffer ) ) ) - { - break; - } - } - - if( dvdplay_position( vmg ) == dvdplay_title_end( vmg ) ) - fManager->Done(); - - /* Clean up */ - dvdplay_close( vmg ); -} diff --git a/HBDVDReader.h b/HBDVDReader.h deleted file mode 100644 index 55db069a8..000000000 --- a/HBDVDReader.h +++ /dev/null @@ -1,23 +0,0 @@ -/* $Id: HBDVDReader.h,v 1.3 2003/08/12 20:10:50 titer Exp $ */ - -#ifndef HB_DVD_READER_H -#define HB_DVD_READER_H - -#include "HBThread.h" -class HBManager; -class HBTitleInfo; -class HBFifo; - -class HBDVDReader : public HBThread -{ - public: - HBDVDReader( HBManager * manager, HBTitleInfo * titleInfo ); - - private: - void DoWork(); - - HBManager * fManager; - HBTitleInfo * fTitleInfo; -}; - -#endif diff --git a/HBFifo.cpp b/HBFifo.cpp deleted file mode 100644 index b85361c56..000000000 --- a/HBFifo.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/* $Id: HBFifo.cpp,v 1.11 2003/08/26 07:48:36 titer Exp $ */ - -#include "HBCommon.h" -#include "HBFifo.h" - -#include <Locker.h> - -HBBuffer::HBBuffer( int size ) -{ - fAllocSize = size; - fSize = size; - fKeyFrame = false; - fData = (uint8_t*) malloc( size ); - - if( !fData ) - { - Log( "HBBuffer::HBBuffer() : malloc() failed, gonna crash soon" ); - } -} - -HBBuffer::~HBBuffer() -{ - free( fData ); -} - -void HBBuffer::ReAlloc( int size ) -{ - fData = (uint8_t*) realloc( fData, size ); - - if( !fData ) - { - Log( "HBBuffer::ReAlloc() : realloc() failed, gonna crash soon" ); - } - - fAllocSize = size; -} - -/* Constructor */ -HBFifo::HBFifo( int capacity ) -{ - fCapacity = capacity; - - fWhereToPush = 0; - fWhereToPop = 0; - fBuffers = (HBBuffer**) malloc( ( fCapacity + 1 ) * sizeof( void* ) ); - fLocker = new BLocker(); - fDie = false; -} - -void HBFifo::Die() -{ - Lock(); - - /* Empty the fifo */ - while( fWhereToPush != fWhereToPop ) - { - HBBuffer * buffer = fBuffers[fWhereToPop]; - fWhereToPop++; - fWhereToPop %= ( fCapacity + 1 ); - delete buffer; - } - - fDie = true; - - Unlock(); -} - -HBFifo::~HBFifo() -{ - /* Empty the fifo */ - while( fWhereToPush != fWhereToPop ) - { - HBBuffer * buffer = fBuffers[fWhereToPop]; - fWhereToPop++; - fWhereToPop %= ( fCapacity + 1 ); - delete buffer; - } - - /* Cleaning */ - free( fBuffers ); - delete fLocker; -} - -/* Size() : returns how much the fifo is currently filled */ -int HBFifo::Size() -{ - return ( fCapacity + 1 + fWhereToPush - fWhereToPop ) % - ( fCapacity + 1 ); -} - -/* Capacity() : simply returns the fifo capacity... */ -int HBFifo::Capacity() -{ - return fCapacity; -} - -/* Push() : add a packet to the fifo. If the fifo is full, it blocks - until the packet can be added. Returns true when it is successful, - or false if the fifo has been destroyed before we could add it */ -bool HBFifo::Push( HBBuffer * buffer ) -{ - bool success = false; - - while( !fDie ) - { - Lock(); - if( Size() < fCapacity ) - { - fBuffers[fWhereToPush] = buffer; - fWhereToPush++; - fWhereToPush %= ( fCapacity + 1 ); - Unlock(); - success = true; - break; - } - Unlock(); - snooze( 10000 ); - } - - if( !success ) - { - delete buffer; - } - - return success; -} - -/* Pop() : get the first packet if the fifo. If the fifo is empty, it - blocks until a packet comes. Returns true when it is successful, - or false if the fifo has been destroyed before we could get a packet */ -HBBuffer * HBFifo::Pop() -{ - while( !fDie ) - { - Lock(); - if( fWhereToPush != fWhereToPop ) - { - HBBuffer * buffer = fBuffers[fWhereToPop]; - fWhereToPop++; - fWhereToPop %= ( fCapacity + 1 ); - Unlock(); - return buffer; - } - Unlock(); - snooze( 10000 ); - } - - return NULL; -} - -/* Lock() : private function */ -void HBFifo::Lock() -{ - fLocker->Lock(); -} - -/* Unlock() : private function */ -void HBFifo::Unlock() -{ - fLocker->Unlock(); -} diff --git a/HBFifo.h b/HBFifo.h deleted file mode 100644 index a46d46158..000000000 --- a/HBFifo.h +++ /dev/null @@ -1,61 +0,0 @@ -/* $Id: HBFifo.h,v 1.9 2003/08/24 13:27:41 titer Exp $ */ - -#ifndef _HB_FIFO_H -#define _HB_FIFO_H - -#define DVD_DATA 0x01 -#define MPEG2_VIDEO 0x02 -#define RAW_VIDEO 0x04 -#define RAW2_VIDEO 0x08 -#define MPEG4_VIDEO 0x10 -#define AC3_AUDIO 0x20 -#define RAW_AUDIO 0x40 -#define MP3_AUDIO 0x80 - -class BLocker; - -class HBBuffer -{ - public: - /* Common functions */ - HBBuffer( int size ); - ~HBBuffer(); - void ReAlloc( int size ); - - /* Common members */ - uint32_t fAllocSize; - uint32_t fSize; - uint8_t * fData; - - /* Misc */ - float fPosition; - uint32_t fStreamId; - bool fKeyFrame; - uint64_t fPTS; -}; - -class HBFifo -{ - public: - HBFifo( int capacity ); - void Die(); - ~HBFifo(); - - int Size(); - int Capacity(); - bool Push( HBBuffer * buffer ); - HBBuffer * Pop(); - - private: - void Lock(); - void Unlock(); - - int fCapacity; - int fWhereToPush; - int fWhereToPop; - HBBuffer ** fBuffers; - BLocker * fLocker; - volatile bool fDie; -}; - -#endif diff --git a/HBManager.cpp b/HBManager.cpp deleted file mode 100644 index 528a58afe..000000000 --- a/HBManager.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* $Id: HBManager.cpp,v 1.28 2003/08/24 21:56:03 titer Exp $ */ - -#include "HBCommon.h" -#include "HBManager.h" -#include "HBWindow.h" -#include "HBFifo.h" -#include "HBDVDReader.h" -#include "HBMpegDemux.h" -#include "HBMpeg2Decoder.h" -#include "HBMpeg4Encoder.h" -#include "HBAc3Decoder.h" -#include "HBMp3Encoder.h" -#include "HBAviMuxer.h" - -#include <Directory.h> -#include <Drivers.h> -#include <Path.h> -#include <Query.h> -#include <String.h> -#include <VolumeRoster.h> - -#include <fs_info.h> -#include <sys/ioctl.h> - -/* Public methods */ - -HBManager::HBManager( HBWindow * window ) - : BLooper( "manager" ) -{ - fWindow = window; - fFifoList = new BList(); - fThreadList = new BList(); - fVolumeList = new BList(); - - Run(); -} - -HBManager::~HBManager() -{ - delete fFifoList; - delete fThreadList; - delete fVolumeList; -} - -void HBManager::MessageReceived( BMessage * message ) -{ - switch( message->what ) - { - case DETECT_VOLUMES: - { - DetectVolumes(); - break; - } - - default: - BLooper::MessageReceived( message ); - } -} - -void HBManager::SetPosition( float position ) -{ - if( position - fPosition < 0.0001 ) - /* No need to be more precise ;) */ - return; - - fPosition = position; - - char statusText[128]; memset( statusText, 0, 128 ); - sprintf( statusText, "Encoding : %.2f %% - %.2f fps (average : %.2f fps)", - 100 * fPosition, fCurrentFrameRate, fAverageFrameRate ); - Status( statusText, fPosition, ENABLE_ENCODING ); -} - -void HBManager::SetFrameRate( float current, float average ) -{ - fCurrentFrameRate = current; - fAverageFrameRate = average; - - char statusText[128]; memset( statusText, 0, 128 ); - sprintf( statusText, "Encoding : %.2f %% - %.2f fps (average : %.2f fps)", - 100 * fPosition, fCurrentFrameRate, fAverageFrameRate ); - Status( statusText, fPosition, ENABLE_ENCODING ); -} - -void HBManager::Start( HBVolumeInfo * volumeInfo, - HBTitleInfo * titleInfo, - HBAudioInfo * audio1Info, - HBAudioInfo * audio2Info, - char * file ) -{ - fPosition = 0; - fCurrentFrameRate = 0; - fAverageFrameRate = 0; - - /* Remember the fifos that should be freezed in Stop() */ - fFifoList->AddItem( ( titleInfo->fPSFifo = new HBFifo( 1024 ) ) ); - fFifoList->AddItem( ( titleInfo->fMpeg2Fifo = new HBFifo( 5 ) ) ); - fFifoList->AddItem( ( titleInfo->fRawFifo = new HBFifo( 5 ) ) ); - fFifoList->AddItem( ( titleInfo->fMpeg4Fifo = new HBFifo( 5 ) ) ); - - /* Create the threads */ - fThreadList->AddItem( new HBDVDReader( this, titleInfo ) ); - fThreadList->AddItem( new HBMpegDemux( this, titleInfo, - audio1Info, audio2Info ) ); - fThreadList->AddItem( new HBMpeg2Decoder( this, titleInfo ) ); - fThreadList->AddItem( new HBMpeg4Encoder( this, titleInfo ) ); - - if( audio1Info->fId ) - { - fFifoList->AddItem( ( audio1Info->fAc3Fifo = new HBFifo( 5 ) ) ); - fFifoList->AddItem( ( audio1Info->fRawFifo = new HBFifo( 5 ) ) ); - fFifoList->AddItem( ( audio1Info->fMp3Fifo = new HBFifo( 5 ) ) ); - fThreadList->AddItem( new HBAc3Decoder( this, audio1Info ) ); - fThreadList->AddItem( new HBMp3Encoder( this, audio1Info ) ); - } - - if( audio2Info->fId ) - { - fFifoList->AddItem( ( audio2Info->fAc3Fifo = new HBFifo( 5 ) ) ); - fFifoList->AddItem( ( audio2Info->fRawFifo = new HBFifo( 5 ) ) ); - fFifoList->AddItem( ( audio2Info->fMp3Fifo = new HBFifo( 5 ) ) ); - fThreadList->AddItem( new HBAc3Decoder( this, audio2Info ) ); - fThreadList->AddItem( new HBMp3Encoder( this, audio2Info ) ); - } - - fThreadList->AddItem( new HBAviMuxer( this, titleInfo, audio1Info, - audio2Info, file ) ); - - /* Run ! */ - HBThread * thread; - for( int i = 0; i < fThreadList->CountItems(); i++ ) - { - thread = (HBThread*) fThreadList->ItemAt( i ); - thread->Run(); - } -} - -void HBManager::Suspend() -{ - HBThread * thread; - for( int i = 0; i < fThreadList->CountItems(); i++ ) - { - thread = (HBThread*) fThreadList->ItemAt( i ); - thread->Suspend(); - } -} - -void HBManager::Resume() -{ - HBThread * thread; - for( int i = 0; i < fThreadList->CountItems(); i++ ) - { - thread = (HBThread*) fThreadList->ItemAt( i ); - thread->Resume(); - } -} - -bool HBManager::Cancel() -{ - if( !( fFifoList->CountItems() ) ) - /* Not running */ - return false; - - Status( "Cancelled.", 0.0, ENABLE_READY ); - Stop(); - - return true; -} - -/* Called by the DVD reader */ -void HBManager::Done() -{ - HBFifo * fifo = NULL; - for( int i = 0; i < fFifoList->CountItems(); i++ ) - { - fifo = (HBFifo*) fFifoList->ItemAt( i ); - - /* Wait until all threads have finished */ - while( fifo->Size() > 0 ) - snooze( 5000 ); - } - - char statusText[128]; memset( statusText, 0, 128 ); - sprintf( statusText, "Done (%.2f fps).", fAverageFrameRate ); - Status( statusText, 1.0, ENABLE_READY ); - Stop(); -} - -void HBManager::Error() -{ - Status( "An error occured.", 0.0, ENABLE_READY ); - Stop(); -} - -/* Private */ - -void HBManager::Stop() -{ - /* Freeze fifos */ - for( int i = 0; i < fFifoList->CountItems(); i++ ) - { - ((HBFifo*) fFifoList->ItemAt( i ))->Die(); - } - - /* Stop threads */ - HBThread * thread; - while( ( thread = (HBThread*) fThreadList->ItemAt( 0 ) ) ) - { - fThreadList->RemoveItem( thread ); - delete thread; - } - - /* Destroy fifos */ - HBFifo * fifo; - while( ( fifo = (HBFifo*) fFifoList->ItemAt( 0 ) ) ) - { - fFifoList->RemoveItem( fifo ); - delete fifo; - } -} - -void HBManager::DetectVolumes() -{ - /* Empty the current list */ - HBVolumeInfo * volumeInfo; - while( ( volumeInfo = (HBVolumeInfo*) fVolumeList->ItemAt( 0 ) ) ) - { - fVolumeList->RemoveItem( volumeInfo ); - delete volumeInfo; - } - - /* Detect the DVD drives by parsing mounted volumes */ - BVolumeRoster * roster = new BVolumeRoster(); - BVolume * volume = new BVolume(); - fs_info info; - int device; - device_geometry geometry; - - while( roster->GetNextVolume( volume ) == B_NO_ERROR ) - { - /* open() and ioctl() for more informations */ - fs_stat_dev( volume->Device(), &info ); - if( ( device = open( info.device_name, O_RDONLY ) ) < 0 ) - continue; - - if( ioctl( device, B_GET_GEOMETRY, &geometry, - sizeof( geometry ) ) < 0 ) - continue; - - /* Get the volume name */ - char volumeName[B_FILE_NAME_LENGTH]; - volume->GetName( volumeName ); - - if( volume->IsReadOnly() && geometry.device_type == B_CD ) - { - /* May be a DVD */ - - /* Try to open the device */ - volumeInfo = new HBVolumeInfo( volumeName, - info.device_name ); - - if( !volumeInfo->InitCheck() ) - { - delete volumeInfo; - continue; - } - - fVolumeList->AddItem( volumeInfo ); - } - else if( geometry.device_type == B_DISK ) - { - /* May be a hard drive. Look for VIDEO_TS folders on it */ - - BQuery * query = new BQuery(); - - if( query->SetVolume( volume ) != B_OK ) - { - delete query; - continue; - } - - if( query->SetPredicate( "name = VIDEO_TS.BUP" ) != B_OK ) - { - delete query; - continue; - } - - query->Fetch(); - - BEntry entry, parentEntry; - BPath path; - while( query->GetNextEntry( &entry ) == B_OK ) - { - entry.GetParent( &parentEntry ); - parentEntry.GetPath( &path ); - - /* Try to open the folder */ - volumeInfo = new HBVolumeInfo( (char*) path.Path(), - (char*) path.Path() ); - - if( !volumeInfo->InitCheck() ) - { - delete volumeInfo; - continue; - } - - fVolumeList->AddItem( volumeInfo ); - } - - delete query; - } - } - - /* Refresh the interface */ - BMessage * message = new BMessage( VOLUMES_DETECTED ); - message->AddPointer( "list", fVolumeList ); - fWindow->PostMessage( message ); - delete message; -} diff --git a/HBManager.h b/HBManager.h deleted file mode 100644 index c1cabca15..000000000 --- a/HBManager.h +++ /dev/null @@ -1,55 +0,0 @@ -/* $Id: HBManager.h,v 1.25 2003/08/24 13:55:18 titer Exp $ */ - -#ifndef _HB_MANAGER_H -#define _HB_MANAGER_H - -#include <Looper.h> - -class HBWindow; -class HBPictureWin; -class HBFifo; - -class HBManager : public BLooper -{ - public: - HBManager( HBWindow * window ); - ~HBManager(); - virtual void MessageReceived( BMessage * message ); - - /* Methods called by the interface */ - void Start( HBVolumeInfo * volumeInfo, - HBTitleInfo * titleInfo, - HBAudioInfo * audio1Info, - HBAudioInfo * audio2Info, - char * file ); - void Suspend(); - void Resume(); - bool Cancel(); - - /* Methods called by the working threads */ - void SetPosition( float position ); - void SetFrameRate( float current, float average ); - void Done(); - void Error(); - - private: - void Stop(); - void DetectVolumes(); - - /* Interface */ - HBWindow * fWindow; - - /* Fifos & threads */ - BList * fThreadList; - BList * fFifoList; - - /* DVD infos */ - BList * fVolumeList; - - /* Status infos */ - float fPosition; - float fCurrentFrameRate; - float fAverageFrameRate; -}; - -#endif diff --git a/HBMp3Encoder.h b/HBMp3Encoder.h deleted file mode 100644 index d8f6ce3f9..000000000 --- a/HBMp3Encoder.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id: HBMp3Encoder.h,v 1.4 2003/08/25 20:41:51 titer Exp $ */ - -#ifndef HB_MP3_ENCODER_H -#define HB_MP3_ENCODER_H - -#include "HBThread.h" -class HBAudioInfo; -class HBManager; -class HBBuffer; -class HBFifo; - -class HBMp3Encoder : public HBThread -{ - public: - HBMp3Encoder( HBManager * manager, HBAudioInfo * audioInfo ); - - private: - void DoWork(); - bool GetSamples( uint32_t count ); - - HBManager * fManager; - HBAudioInfo * fAudioInfo; - - HBBuffer * fRawBuffer; - uint32_t fPosInBuffer; /* in samples */ - float * fLeftSamples; - float * fRightSamples; -}; - -#endif diff --git a/HBMpeg2Decoder.cpp b/HBMpeg2Decoder.cpp deleted file mode 100644 index f65f2df6b..000000000 --- a/HBMpeg2Decoder.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* $Id: HBMpeg2Decoder.cpp,v 1.25 2003/08/23 19:38:47 titer Exp $ */ - -#include "HBCommon.h" -#include "HBManager.h" -#include "HBMpeg2Decoder.h" -#include "HBFifo.h" - -extern "C" { -#include <mpeg2dec/mpeg2.h> -} -#include <ffmpeg/avcodec.h> - -HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitleInfo * titleInfo ) - : HBThread( "mpeg2decoder" ) -{ - fManager = manager; - fTitleInfo = titleInfo; -} - -void HBMpeg2Decoder::DoWork() -{ - /* Statistics */ - uint32_t framesSinceLast = 0; - uint32_t framesSinceBegin = 0; - uint64_t lastTime = 0; - uint64_t beginTime = 0; - - /* Init buffers */ - HBBuffer * mpeg2Buffer = NULL; - HBBuffer * rawBuffer = NULL; - HBBuffer * deinterlacedBuffer = NULL; - HBBuffer * resizedBuffer = NULL; - AVPicture * rawPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); - AVPicture * deinterlacedPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); - AVPicture * resizedPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); - - /* Init libmpeg2 */ - mpeg2dec_t * handle = mpeg2_init(); - const mpeg2_info_t * info = mpeg2_info( handle ); - - /* libavcodec */ - ImgReSampleContext * resampleContext = NULL; - - /* NTSC 3:2 pulldown kludge - UGLY ! */ - if( fTitleInfo->fScale == 900900 ) - { - fTitleInfo->fScale = 1125000; - } - - /* Resizing & cropping initializations */ - resampleContext = img_resample_full_init( fTitleInfo->fOutWidth, fTitleInfo->fOutHeight, - fTitleInfo->fInWidth, fTitleInfo->fInHeight, - fTitleInfo->fTopCrop, fTitleInfo->fBottomCrop, - fTitleInfo->fLeftCrop, fTitleInfo->fRightCrop ); - rawBuffer = new HBBuffer( 3 * fTitleInfo->fInWidth * fTitleInfo->fInHeight / 2 ); - deinterlacedBuffer = new HBBuffer( 3 * fTitleInfo->fInWidth * fTitleInfo->fInHeight / 2 ); - avpicture_fill( rawPicture, rawBuffer->fData, - PIX_FMT_YUV420P, fTitleInfo->fInWidth, fTitleInfo->fInHeight ); - avpicture_fill( deinterlacedPicture, deinterlacedBuffer->fData, - PIX_FMT_YUV420P, fTitleInfo->fInWidth, fTitleInfo->fInHeight ); - - /* Init statistics */ - lastTime = system_time(); - beginTime = system_time(); - - Log( "HBMpeg2Decoder : %dx%d -> %dx%d, %.2f fps", - fTitleInfo->fInWidth, fTitleInfo->fInHeight, - fTitleInfo->fOutWidth, fTitleInfo->fOutHeight, - (float) fTitleInfo->fRate / fTitleInfo->fScale ); - - /* Main loop */ - mpeg2_state_t state; - for( ;; ) - { - state = mpeg2_parse( handle ); - - if( state == STATE_BUFFER ) - { - /* Free the previous buffer */ - if( mpeg2Buffer ) - delete mpeg2Buffer; - - /* Get a new one */ - if( !( mpeg2Buffer = fTitleInfo->fMpeg2Fifo->Pop() ) ) - break; - - /* Feed libmpeg2 */ - mpeg2_buffer( handle, mpeg2Buffer->fData, - mpeg2Buffer->fData + mpeg2Buffer->fSize ); - } - else if( ( state == STATE_SLICE || state == STATE_END ) && - info->display_fbuf ) - { - /* Got a raw picture */ - - /* Copy it */ - /* TODO : make libmpeg2 write directly in our buffer */ - memcpy( rawBuffer->fData, - info->display_fbuf->buf[0], - fTitleInfo->fInWidth * fTitleInfo->fInHeight ); - memcpy( rawBuffer->fData + fTitleInfo->fInWidth * fTitleInfo->fInHeight, - info->display_fbuf->buf[1], - fTitleInfo->fInWidth * fTitleInfo->fInHeight / 4 ); - memcpy( rawBuffer->fData + fTitleInfo->fInWidth * fTitleInfo->fInHeight + - fTitleInfo->fInWidth * fTitleInfo->fInHeight / 4, - info->display_fbuf->buf[2], - fTitleInfo->fInWidth * fTitleInfo->fInHeight / 4 ); - - resizedBuffer = new HBBuffer( 3 * fTitleInfo->fOutWidth * fTitleInfo->fOutHeight / 2 ); - avpicture_fill( resizedPicture, resizedBuffer->fData, PIX_FMT_YUV420P, - fTitleInfo->fOutWidth, fTitleInfo->fOutHeight ); - - if( fTitleInfo->fDeinterlace ) - { - avpicture_deinterlace( deinterlacedPicture, rawPicture, PIX_FMT_YUV420P, - fTitleInfo->fInWidth, fTitleInfo->fInHeight ); - img_resample( resampleContext, resizedPicture, - deinterlacedPicture ); - } - else - { - img_resample( resampleContext, resizedPicture, rawPicture ); - } - - /* Send it to the encoder */ - if( !( fTitleInfo->fRawFifo->Push( resizedBuffer ) ) ) - { - break; - } - - /* Update GUI position */ - fManager->SetPosition( mpeg2Buffer->fPosition ); - - /* Statistics every 0.5 second */ - framesSinceLast++; - framesSinceBegin++; - if( system_time() - lastTime > 500000 ) - { - fManager->SetFrameRate( 1000000 * (float) framesSinceLast / - (float) ( system_time() - lastTime ), - 1000000 * (float) framesSinceBegin / - (float) ( system_time() - beginTime ) ); - lastTime = system_time(); - framesSinceLast = 0; - } - - } - else if( state == STATE_INVALID ) - { - /* Shouldn't happen on a DVD */ - Log( "HBMpeg2Decoder : STATE_INVALID" ); - } - } - - /* Close libmpeg2 */ - mpeg2_close( handle ); - - /* Close libavcodec */ - img_resample_close( resampleContext ); - - /* Free structures & buffers */ - if( mpeg2Buffer ) delete mpeg2Buffer; - if( rawBuffer ) delete rawBuffer; - if( deinterlacedBuffer ) delete deinterlacedBuffer; - if( rawPicture ) free( rawPicture ); - if( deinterlacedPicture ) free( deinterlacedPicture ); - if( resizedPicture ) free( resizedPicture ); -} diff --git a/HBMpeg2Decoder.h b/HBMpeg2Decoder.h deleted file mode 100644 index 00e05dd57..000000000 --- a/HBMpeg2Decoder.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id: HBMpeg2Decoder.h,v 1.9 2003/08/16 10:17:38 titer Exp $ */ - -#ifndef _HB_MPEG2_DECODER_H -#define _HB_MPEG2_DECODER_H - -#include "HBThread.h" -class HBManager; -class HBBuffer; -class HBFifo; - -typedef struct mpeg2dec_s mpeg2dec_t; -typedef struct AVPicture AVPicture; -typedef struct ImgReSampleContext ImgReSampleContext; - -class HBMpeg2Decoder : public HBThread -{ - public: - HBMpeg2Decoder( HBManager * manager, HBTitleInfo * titleInfo ); - - private: - void DoWork(); - - HBManager * fManager; - HBTitleInfo * fTitleInfo; -}; - -#endif diff --git a/HBMpeg4Encoder.cpp b/HBMpeg4Encoder.cpp deleted file mode 100644 index f8682330b..000000000 --- a/HBMpeg4Encoder.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* $Id: HBMpeg4Encoder.cpp,v 1.18 2003/08/23 19:38:47 titer Exp $ */ - -#include "HBCommon.h" -#include "HBMpeg4Encoder.h" -#include "HBManager.h" -#include "HBFifo.h" - -#include <ffmpeg/avcodec.h> - -HBMpeg4Encoder::HBMpeg4Encoder( HBManager * manager, HBTitleInfo * titleInfo ) - : HBThread( "mpeg4encoder" ) -{ - fManager = manager; - fTitleInfo = titleInfo; -} - -void HBMpeg4Encoder::DoWork() -{ - /* Init libavcodec */ - AVCodec * codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); - if( !codec ) - { - Log( "HBMpeg4Encoder: avcodec_find_encoder() failed" ); - fManager->Error(); - return; - } - -#define WIDTH fTitleInfo->fOutWidth -#define HEIGHT fTitleInfo->fOutHeight -#define RATE fTitleInfo->fRate -#define SCALE fTitleInfo->fScale - - AVCodecContext * context; - context = avcodec_alloc_context(); - context->bit_rate = 1024 * fTitleInfo->fBitrate; - context->bit_rate_tolerance = 1024 * fTitleInfo->fBitrate; - context->flags |= CODEC_FLAG_HQ; - context->width = WIDTH; - context->height = HEIGHT; - context->frame_rate = RATE; - context->frame_rate_base = SCALE; - context->gop_size = 10 * RATE / SCALE; - - if( avcodec_open( context, codec ) < 0 ) - { - Log( "HBMpeg4Encoder: avcodec_open() failed" ); - fManager->Error(); - return; - } - - AVFrame * frame = avcodec_alloc_frame(); - HBBuffer * mpeg4Buffer; - - for( ;; ) - { - /* Get another frame */ - if( !( fRawBuffer = fTitleInfo->fRawFifo->Pop() ) ) - break; - - frame->data[0] = fRawBuffer->fData; - frame->data[1] = frame->data[0] + WIDTH * HEIGHT; - frame->data[2] = frame->data[1] + WIDTH * HEIGHT / 4; - frame->linesize[0] = WIDTH; - frame->linesize[1] = WIDTH / 2; - frame->linesize[2] = WIDTH / 2; - - mpeg4Buffer = new HBBuffer( 3 * WIDTH * HEIGHT / 2 ); - /* Should be too much. It can't be bigger than the raw video ! */ - - mpeg4Buffer->fSize = - avcodec_encode_video( context, mpeg4Buffer->fData, - mpeg4Buffer->fAllocSize, frame ); - mpeg4Buffer->fKeyFrame = ( context->coded_frame->key_frame != 0 ); - -#undef WIDTH -#undef HEIGHT -#undef RATE -#undef SCALE - - delete fRawBuffer; - - /* Mux it */ - if( !fTitleInfo->fMpeg4Fifo->Push( mpeg4Buffer ) ) - { - break; - } - } -} diff --git a/HBMpeg4Encoder.h b/HBMpeg4Encoder.h deleted file mode 100644 index 3f5ccacfa..000000000 --- a/HBMpeg4Encoder.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id: HBMpeg4Encoder.h,v 1.4 2003/08/05 16:47:19 titer Exp $ */ - -#ifndef _HB_MPEG4_ENCODER_H -#define _HB_MPEG4_ENCODER_H - -#include "HBThread.h" -class HBManager; -class HBFifo; -class HBAudioInfo; -class HBTitleInfo; -class HBBuffer; - -class HBMpeg4Encoder : public HBThread -{ - public: - HBMpeg4Encoder( HBManager * manager, HBTitleInfo * titleInfo ); - - private: - void DoWork(); - - HBManager * fManager; - HBTitleInfo * fTitleInfo; - - HBBuffer * fRawBuffer; -}; - -#endif diff --git a/HBMpegDemux.h b/HBMpegDemux.h deleted file mode 100644 index f98c0a0ae..000000000 --- a/HBMpegDemux.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $Id: HBMpegDemux.h,v 1.7 2003/08/24 13:27:41 titer Exp $ */ - -#ifndef _HB_MPEG_DEMUX_H -#define _HB_MPEG_DEMUX_H - -#include "HBThread.h" -class HBManager; -class HBBuffer; -class BList; - -BList * PStoES( HBBuffer * psBuffer ); - -class HBMpegDemux : public HBThread -{ - public: - HBMpegDemux( HBManager * manager, HBTitleInfo * titleInfo, - HBAudioInfo * audio1Info, HBAudioInfo * audio2Info ); - - private: - void DoWork(); - void InsertSilence( int64_t time, HBFifo * fifo, - HBBuffer * buffer ); - - HBManager * fManager; - HBTitleInfo * fTitleInfo; - HBAudioInfo * fAudio1Info; - HBAudioInfo * fAudio2Info; - - HBBuffer * fPSBuffer; - HBBuffer * fESBuffer; - BList * fESBufferList; - - int64_t fFirstVideoPTS; - int64_t fFirstAudio1PTS; - int64_t fFirstAudio2PTS; -}; - -#endif diff --git a/HBPictureWin.cpp b/HBPictureWin.cpp deleted file mode 100644 index 8fd9e8405..000000000 --- a/HBPictureWin.cpp +++ /dev/null @@ -1,290 +0,0 @@ -/* $Id: HBPictureWin.cpp,v 1.15 2003/08/25 21:50:48 titer Exp $ */ - -#include "HBCommon.h" -#include "HBPictureWin.h" -#include "HBManager.h" - -#include <Bitmap.h> -#include <Box.h> -#include <CheckBox.h> -#include <Slider.h> - -#include <ffmpeg/avcodec.h> - -#define UPDATE_BITMAP 'upbi' - -/* Handy way to access HBTitleInfo members */ -#define fInWidth fTitleInfo->fInWidth -#define fInHeight fTitleInfo->fInHeight -#define fPixelWidth fTitleInfo->fPixelWidth -#define fPixelHeight fTitleInfo->fPixelHeight -#define fDeinterlace fTitleInfo->fDeinterlace -#define fOutWidth fTitleInfo->fOutWidth -#define fOutHeight fTitleInfo->fOutHeight -#define fTopCrop fTitleInfo->fTopCrop -#define fBottomCrop fTitleInfo->fBottomCrop -#define fLeftCrop fTitleInfo->fLeftCrop -#define fRightCrop fTitleInfo->fRightCrop -#define fPictures fTitleInfo->fPictures - -HBPictureView::HBPictureView( BRect rect, BBitmap * bitmap ) - : BView( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW ) -{ - fBitmap = bitmap; -} - -void HBPictureView::Draw( BRect rect ) -{ - if( LockLooper() ) - { - DrawBitmap( fBitmap, Bounds() ); - UnlockLooper(); - } - else - { - Log( "HBPictureView::Draw() : LockLooper() failed" ); - } - - BView::Draw( rect ); -} - - -/* Constructor */ -HBPictureWin::HBPictureWin( HBTitleInfo * titleInfo ) - : BWindow( BRect( 50, 50, 60, 60 ), "Picture settings", - B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE ) -{ - fTitleInfo = titleInfo; - - fMaxOutWidth = MULTIPLE_16( fInWidth ); - fMaxOutHeight = MULTIPLE_16( fInHeight * fPixelHeight / fPixelWidth ); - - /* Leave a one-pixel margin to draw the white line around the picture */ - fBitmap = new BBitmap( BRect( 0, 0, fMaxOutWidth + 1, fMaxOutHeight + 1 ), - 0, B_RGB32 ); - - ResizeTo( fMaxOutWidth + 40, fMaxOutHeight + 331 ); - - BRect r; - - /* Add a background view */ - BView * view; - view = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW ); - view->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); - AddChild( view ); - - /* First box : picture + slider */ - r = BRect( 10, 10, fMaxOutWidth + 31, fMaxOutHeight + 68 ); - BBox * pictureBox; - pictureBox = new BBox( r, NULL ); - pictureBox->SetLabel( "Preview" ); - - /* Picture view */ - r = BRect( 10, 15, fMaxOutWidth + 11, fMaxOutHeight + 16 ); - fPictureView = new HBPictureView( r, fBitmap ); - pictureBox->AddChild( fPictureView ); - - /* Slider */ - r = BRect( 10, fMaxOutHeight + 26, fMaxOutWidth + 10, fMaxOutHeight + 56 ); - fPictureSlider = new BSlider( r, NULL, NULL, new BMessage( UPDATE_BITMAP ), 0, 9 ); - pictureBox->AddChild( fPictureSlider ); - - view->AddChild( pictureBox ); - - /* Second box : resize & crop settings */ - r = BRect( 10, fMaxOutHeight + 76, fMaxOutWidth + 30, fMaxOutHeight + 321 ); - BBox * settingsBox; - settingsBox = new BBox( r, NULL ); - settingsBox->SetLabel( "Settings" ); - - r = BRect( 10, 15, fMaxOutWidth + 10, 45 ); - fWidthSlider = new BSlider( r, NULL, "Picture size", - new BMessage( UPDATE_BITMAP ), - 1, fMaxOutWidth / 16, - B_TRIANGLE_THUMB ); - fWidthSlider->SetValue( fMaxOutWidth / 16 ); - settingsBox->AddChild( fWidthSlider ); - - r = BRect( 10, 55, fMaxOutWidth + 10, 85 ); - fTopCropSlider = new BSlider( r, NULL, "Top cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInHeight / 4, - B_TRIANGLE_THUMB ); - settingsBox->AddChild( fTopCropSlider ); - - r = BRect( 10, 95, fMaxOutWidth + 10, 125 ); - fBottomCropSlider = new BSlider( r, NULL, "Bottom cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInHeight / 4, - B_TRIANGLE_THUMB ); - settingsBox->AddChild( fBottomCropSlider ); - - r = BRect( 10, 135, fMaxOutWidth + 10, 165 ); - fLeftCropSlider = new BSlider( r, NULL, "Left cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInWidth / 4, - B_TRIANGLE_THUMB ); - settingsBox->AddChild( fLeftCropSlider ); - - r = BRect( 10, 175, fMaxOutWidth + 10, 205 ); - fRightCropSlider = new BSlider( r, NULL, "Right cropping", - new BMessage( UPDATE_BITMAP ), - 0, fInWidth / 4, - B_TRIANGLE_THUMB ); - settingsBox->AddChild( fRightCropSlider ); - - r = BRect( 10, 215, fMaxOutWidth + 10, 235 ); - fDeinterlaceCheck = new BCheckBox( r, NULL, "Deinterlace", - new BMessage( UPDATE_BITMAP ) ); - settingsBox->AddChild( fDeinterlaceCheck ); - - view->AddChild( settingsBox ); - - /* Buttons */ - - - Hide(); - Show(); - - UpdateBitmap( 0 ); -} - -bool HBPictureWin::QuitRequested() -{ - if( Lock() ) - { - Hide(); - Unlock(); - } - else - { - Log( "HBPictureWin::QuitRequested : cannot Lock()" ); - } - return false; -} - -void HBPictureWin::MessageReceived( BMessage * message ) -{ - switch( message->what ) - { - case UPDATE_BITMAP: - UpdateBitmap( fPictureSlider->Value() ); - fPictureView->Draw( fPictureView->Bounds() ); - break; - - default: - BWindow::MessageReceived( message ); - } -} - -void HBPictureWin::UpdateBitmap( int which ) -{ - fTopCrop = 2 * fTopCropSlider->Value(); - fBottomCrop = 2 * fBottomCropSlider->Value(); - fLeftCrop = 2 * fLeftCropSlider->Value(); - fRightCrop = 2 * fRightCropSlider->Value(); - fDeinterlace = ( fDeinterlaceCheck->Value() != 0 ); - - fOutWidth = MULTIPLE_16( 16 * fWidthSlider->Value() - fLeftCrop - fRightCrop ); - fOutHeight = MULTIPLE_16( ( fInHeight - fTopCrop - fBottomCrop ) * - ( 16 * fWidthSlider->Value() * fPixelHeight ) / - ( fInWidth * fPixelWidth ) ); - - AVPicture pic1; /* original YUV picture */ - avpicture_fill( &pic1, fPictures[which], - PIX_FMT_YUV420P, fInWidth, fInHeight ); - - AVPicture pic2; /* deinterlaced YUV picture */ - uint8_t * buf2 = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 ); - avpicture_fill( &pic2, buf2, PIX_FMT_YUV420P, fInWidth, fInHeight ); - - AVPicture pic3; /* resized YUV picture */ - uint8_t * buf3 = (uint8_t*) malloc( 3 * fOutWidth * fOutHeight / 2 ); - avpicture_fill( &pic3, buf3, PIX_FMT_YUV420P, fOutWidth, fOutHeight ); - - AVPicture pic4; /* resized RGB picture */ - uint8_t * buf4 = (uint8_t*) malloc( 4 * fOutWidth * fOutHeight ); - avpicture_fill( &pic4, buf4, PIX_FMT_RGBA32, fOutWidth, fOutHeight ); - - ImgReSampleContext * resampleContext; - resampleContext = img_resample_full_init( fOutWidth, fOutHeight, - fInWidth, fInHeight, - fTopCrop, fBottomCrop, - fLeftCrop, fRightCrop ); - - if( fDeinterlace ) - { - avpicture_deinterlace( &pic2, &pic1, PIX_FMT_YUV420P, fInWidth, fInHeight ); - img_resample( resampleContext, &pic3, &pic2 ); - } - else - { - img_resample( resampleContext, &pic3, &pic1 ); - } - img_convert( &pic4, PIX_FMT_RGBA32, &pic3, PIX_FMT_YUV420P, fOutWidth, fOutHeight ); - - /* Blank the bitmap */ - for( uint32_t i = 0; i < fMaxOutHeight + 2; i++ ) - { - memset( (uint8_t*) fBitmap->Bits() + i * fBitmap->BytesPerRow(), - 0, ( fMaxOutWidth + 2 ) * 4 ); - } - - /* Draw the picture (centered) */ - uint32_t leftOffset = 1 + ( fMaxOutWidth - fOutWidth ) / 2; - uint32_t topOffset = 1 + ( fMaxOutHeight - fOutHeight ) / 2; - for( uint32_t i = 0; i < fOutHeight; i++ ) - { - memcpy( (uint8_t*) fBitmap->Bits() + - ( i + topOffset ) * fBitmap->BytesPerRow() + - leftOffset * 4, - buf4 + i * fOutWidth * 4, - fOutWidth * 4 ); - } - - /* Draw the cropping zone */ - memset( (uint8_t*) fBitmap->Bits() + - ( topOffset - 1 ) * fBitmap->BytesPerRow() + - ( leftOffset - 1 ) * 4, - 0xFF, - ( fOutWidth + 2 ) * 4 ); - - for( uint32_t i = 0; i < fOutHeight + 2; i++ ) - { - memset( (uint8_t*) fBitmap->Bits() + - ( i + ( topOffset - 1 ) ) * fBitmap->BytesPerRow() + - ( leftOffset - 1 ) * 4, - 0xFF, - 4 ); - memset( (uint8_t*) fBitmap->Bits() + - ( i + ( topOffset - 1 ) ) * fBitmap->BytesPerRow() + - ( leftOffset + fOutWidth ) * 4, - 0xFF, - 4 ); - } - - memset( (uint8_t*) fBitmap->Bits() + - ( topOffset + fOutHeight ) * fBitmap->BytesPerRow() + - ( leftOffset - 1 ) * 4, - 0xFF, - ( fOutWidth + 2 ) * 4 ); - - /* Clean up */ - free( buf2 ); - free( buf3 ); - free( buf4 ); - - /* Show the output size */ - if( !Lock() ) - { - Log( "HBPictureWin::UpdateBitmap() : cannot Lock()" ); - return; - } - - char label[128]; memset( label, 0, 128 ); - snprintf( label, 128, "Picture size : %d x %d", - fOutWidth, fOutHeight ); - fWidthSlider->SetLabel( label ); - - Unlock(); -} diff --git a/HBThread.cpp b/HBThread.cpp deleted file mode 100644 index b36462be0..000000000 --- a/HBThread.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* $Id: HBThread.cpp,v 1.3 2003/08/24 13:27:41 titer Exp $ */ - -#include "HBCommon.h" -#include "HBThread.h" - -#include <OS.h> - -HBThread::HBThread( char * name, int priority = B_LOW_PRIORITY ) -{ - fName = strdup( name ); - fThread = spawn_thread( ThreadFunc, fName, priority, this ); -} - -HBThread::~HBThread() -{ - fDie = true; - Log( "Stopping thread %d (\"%s\")", fThread, fName ); - int32 exit_value; - wait_for_thread( fThread, &exit_value ); - Log( "Thread %d stopped (\"%s\")", fThread, fName ); - free( fName ); -} - -void HBThread::Run() -{ - fDie = false; - resume_thread( fThread ); - Log( "Thread %d started (\"%s\")", fThread, fName ); -} - -void HBThread::Suspend() -{ - suspend_thread( fThread ); -} - -void HBThread::Resume() -{ - resume_thread( fThread ); -} - -long HBThread::ThreadFunc( HBThread * _this ) -{ - _this->DoWork(); - return 0; -} - -void HBThread::DoWork() -{ -} diff --git a/HBThread.h b/HBThread.h deleted file mode 100644 index 5356e5c1f..000000000 --- a/HBThread.h +++ /dev/null @@ -1,26 +0,0 @@ -/* $Id: HBThread.h,v 1.3 2003/08/24 13:27:41 titer Exp $ */ - -#ifndef _HB_THREAD_H -#define _HB_THREAD_H - -class HBThread -{ - public: - HBThread( char * name, int priority = 5 ); - virtual ~HBThread(); - void Run(); - void Suspend(); - void Resume(); - - protected: - volatile bool fDie; - - private: - static long ThreadFunc( HBThread * _this ); - virtual void DoWork(); - - char * fName; - int fThread; -}; - -#endif diff --git a/HBWindow.cpp b/HBWindow.cpp deleted file mode 100644 index 9a6fcaa1d..000000000 --- a/HBWindow.cpp +++ /dev/null @@ -1,633 +0,0 @@ -/* $Id: HBWindow.cpp,v 1.21 2003/08/25 22:04:22 titer Exp $ */ - -#include "HBCommon.h" -#include "HBWindow.h" -#include "HBManager.h" -#include "HBPictureWin.h" - -#include <Alert.h> -#include <Application.h> -#include <Box.h> -#include <Button.h> -#include <MenuField.h> -#include <PopUpMenu.h> -#include <Slider.h> -#include <StatusBar.h> -#include <StringView.h> -#include <TextControl.h> - -#define WINDOW_RECT BRect( 100,100,500,505 ) - -/* HBBox : almost a simple BBox, unless we draw a horizontal line - before the "Picture" and "Advanced" buttons. There must be a - cleaner way to do this, but I'm not a expert GUI programmer. */ - -/* Constructor */ -HBBox::HBBox( BRect rect ) - : BBox( rect, NULL ) -{ -} - -/* Draw */ -void HBBox::Draw( BRect rect ) -{ - /* Inherited method */ - BBox::Draw( rect ); - - /* Draw the line */ - SetHighColor( 120, 120, 120 ); - SetLowColor( 255, 255, 255 ); - StrokeLine( BPoint( 10, 265 ), - BPoint( Bounds().Width() - 10, 265 ), - B_SOLID_HIGH ); - StrokeLine( BPoint( 11, 266 ), - BPoint( Bounds().Width() - 10, 266 ), - B_SOLID_LOW ); -} - -/* HBWindow : the real interface */ - -/* Constructor */ -HBWindow::HBWindow() - : BWindow( WINDOW_RECT, "HandBrake " VERSION, B_TITLED_WINDOW, - B_NOT_RESIZABLE | B_NOT_ZOOMABLE ) -{ - BRect r; - - /* Add a background view */ - BView * view; - view = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW ); - view->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); - AddChild( view ); - - /* Add the settings box */ - r = BRect( 10, 10, view->Bounds().Width() - 10, - view->Bounds().Height() - 85 ); - fBox = new HBBox( r ); - fBox->SetLabel( "Settings" ); - - /* Volume */ - r = BRect( 10, 15, fBox->Bounds().Width() - 10, 35 ); - fVolumePopUp = new BPopUpMenu( "No DVD found" ); - fVolumeField = new BMenuField( r, NULL, "Volume :", - fVolumePopUp, true ); - fBox->AddChild( fVolumeField ); - - /* Title */ - r = BRect( 10, 45, fBox->Bounds().Width() - 10, 65 ); - fTitlePopUp = new BPopUpMenu( "No title found" ); - fTitleField = new BMenuField( r, NULL, "Title :", - fTitlePopUp, true ); - fBox->AddChild( fTitleField ); - - /* Audio 1 */ - r = BRect( 10, 75, fBox->Bounds().Width() - 10, 95 ); - fAudio1PopUp = new BPopUpMenu( "No audio found" ); - fAudio1Field = new BMenuField( r, NULL, "Audio 1 :", - fAudio1PopUp, true ); - fBox->AddChild( fAudio1Field ); - - /* Audio 2 */ - r = BRect( 10, 105, fBox->Bounds().Width() - 10, 125 ); - fAudio2PopUp = new BPopUpMenu( "No audio found" ); - fAudio2Field = new BMenuField( r, NULL, "Audio 2 :", - fAudio2PopUp, true ); - fBox->AddChild( fAudio2Field ); - - /* Video bitrate */ - r = BRect( 10, 135, fBox->Bounds().Width() - 10, 165 ); - fVideoSlider = new BSlider( r, NULL, "Video bitrate : 1024 kbps", - new BMessage( VIDEO_SLIDER ), - 128, 4096, B_TRIANGLE_THUMB ); - fVideoSlider->SetValue( 1024 ); - fBox->AddChild( fVideoSlider ); - - /* Audio bitrate */ - r = BRect( 10, 175, fBox->Bounds().Width() - 10, 205 ); - fAudioSlider = new BSlider( r, NULL, "Audio bitrate : 128 kbps", - new BMessage( AUDIO_SLIDER ), - 64, 384, B_TRIANGLE_THUMB ); - fAudioSlider->SetValue( 128 ); - fBox->AddChild( fAudioSlider ); - - /* Destination file */ - r = BRect( 10, 215, fBox->Bounds().Width() - 10, 230 ); - fFileString = new BStringView( r, NULL, "Destination file :" ); - fBox->AddChild( fFileString ); - r = BRect( 10, 235, fBox->Bounds().Width() - 90, 255 ); - fFileControl = new BTextControl( r, NULL, "", "/boot/home/Desktop/Movie.avi", - new BMessage() ); - fFileControl->SetDivider( 0 ); - fBox->AddChild( fFileControl ); - r = BRect( fBox->Bounds().Width() - 80, 230, - fBox->Bounds().Width() - 10, 255 ); - fFileButton = new BButton( r, NULL, "Browse...", - new BMessage( NOT_IMPLEMENTED ) ); - fBox->AddChild( fFileButton ); - - view->AddChild( fBox ); - - /* Settings buttons */ - r = BRect( fBox->Bounds().Width() - 200, 275, - fBox->Bounds().Width() - 100, 300 ); - fPictureButton = new BButton( r, NULL, "Picture settings...", - new BMessage( PICTURE_WIN ) ); - fBox->AddChild( fPictureButton ); - - r = BRect( fBox->Bounds().Width() - 90, 275, - fBox->Bounds().Width() - 10, 300 ); - fAdvancedButton = new BButton( r, NULL, "Advanced...", - new BMessage( NOT_IMPLEMENTED ) ); - fBox->AddChild( fAdvancedButton ); - - /* Status bar */ - r = BRect( 10, view->Bounds().Height() - 75, - view->Bounds().Width() - 10, view->Bounds().Height() - 45 ); - fStatusBar = new BStatusBar( r, NULL, NULL ); - fStatusBar->SetMaxValue( 1.0 ); - view->AddChild( fStatusBar ); - - /* Buttons */ - r = BRect( view->Bounds().Width() - 320, view->Bounds().Height() - 35, - view->Bounds().Width() - 250, view->Bounds().Height() - 10 ); - BButton * aboutButton; - aboutButton = new BButton( r, NULL, "About...", - new BMessage( B_ABOUT_REQUESTED ) ); - view->AddChild( aboutButton ); - - r = BRect( view->Bounds().Width() - 240, view->Bounds().Height() - 35, - view->Bounds().Width() - 170, view->Bounds().Height() - 10 ); - fRefreshButton = new BButton( r, NULL, "Refresh", - new BMessage( REFRESH_VOLUMES ) ); - view->AddChild( fRefreshButton ); - - r = BRect( view->Bounds().Width() - 160, view->Bounds().Height() - 35, - view->Bounds().Width() - 90, view->Bounds().Height() - 10 ); - fSuspendButton = new BButton( r, NULL, "Suspend", new BMessage( SUSPEND_CONVERT ) ); - view->AddChild( fSuspendButton ); - - r = BRect( view->Bounds().Width() - 80, view->Bounds().Height() - 35, - view->Bounds().Width() - 10, view->Bounds().Height() - 10 ); - fStartButton = new BButton( r, NULL, "Start !", new BMessage( START_CONVERT ) ); - view->AddChild( fStartButton ); -} - -bool HBWindow::QuitRequested() -{ - /* Empty the PopUps - the BMenuItems do not belong to us */ - HBVolumeInfo * volumeInfo; - while( ( volumeInfo = (HBVolumeInfo*) fVolumePopUp->ItemAt( 0 ) ) ) - { - fVolumePopUp->RemoveItem( volumeInfo ); - } - - HBTitleInfo * titleInfo; - while( ( titleInfo = (HBTitleInfo*) fTitlePopUp->ItemAt( 0 ) ) ) - { - fTitlePopUp->RemoveItem( titleInfo ); - } - - HBAudioInfo * audioInfo; - while( ( audioInfo = (HBAudioInfo*) fAudio1PopUp->ItemAt( 0 ) ) ) - { - fAudio1PopUp->RemoveItem( audioInfo ); - } - while( ( audioInfo = (HBAudioInfo*) fAudio2PopUp->ItemAt( 0 ) ) ) - { - fAudio2PopUp->RemoveItem( audioInfo ); - } - - /* Stop the application */ - be_app->PostMessage( B_QUIT_REQUESTED ); - return true; -} - -void HBWindow::MessageReceived( BMessage * message ) -{ - switch( message->what ) - { - case NOT_IMPLEMENTED: - { - /* Warn the user with a BAlert */ - BAlert * alert; - alert = new BAlert( "Not implemented", - "This feature has not yet been implemented.", - "Come back later !" ); - alert->Go( NULL ); - break; - } - - case VOLUME_SELECTED: - case TITLE_SELECTED: - case LANGUAGE_SELECTED: - SelectionChanged(); - break; - - case VIDEO_SLIDER: - { - /* Update the slider label */ - char label[128]; memset( label, 0, 128 ); - snprintf( label, 128, - "Video bitrate : %ld kbps", - fVideoSlider->Value() ); - fVideoSlider->SetLabel( label ); - break; - } - - case AUDIO_SLIDER: - { - /* Update the slider label */ - char label[128]; memset( label, 0, 128 ); - snprintf( label, 128, - "Audio bitrate : %ld kbps", - fAudioSlider->Value() ); - fAudioSlider->SetLabel( label ); - break; - } - - case PICTURE_WIN: - { - HBTitleInfo * titleInfo; - titleInfo = (HBTitleInfo*) fTitlePopUp->FindMarked(); - - if( titleInfo->fPictureWin->Lock() ) - { - titleInfo->fPictureWin->Show(); - titleInfo->fPictureWin->Unlock(); - break; - } - else - { - Log( "Couldn't lock fPictureWin" ); - } - - break; - } - - case SUSPEND_CONVERT: - /* Suspend all threads */ - fManager->Suspend(); - - /* Update the button label */ - if( Lock() ) - { - fSuspendButton->SetLabel( "Resume" ); - fSuspendButton->SetMessage( new BMessage( RESUME_CONVERT ) ); - Unlock(); - } - break; - - case RESUME_CONVERT: - /* Resume all threads */ - fManager->Resume(); - - /* Update the button label */ - if( Lock() ) - { - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetMessage( new BMessage( SUSPEND_CONVERT ) ); - Unlock(); - } - break; - - case START_CONVERT: - { - /* Shouldn't happen */ - if( !fVolumePopUp->FindMarked() || - !fTitlePopUp->FindMarked() || - !fAudio1PopUp->FindMarked() || - !fAudio2PopUp->FindMarked() ) - break; - - /* Disable the interface */ - Status( "Starting...", 0.0, ENABLE_ENCODING ); - - /* Start the job */ - HBVolumeInfo * volumeInfo = (HBVolumeInfo*) fVolumePopUp->FindMarked(); - HBTitleInfo * titleInfo = (HBTitleInfo*) fTitlePopUp->FindMarked(); - HBAudioInfo * audio1Info = (HBAudioInfo*) fAudio1PopUp->FindMarked(); - HBAudioInfo * audio2Info = (HBAudioInfo*) fAudio2PopUp->FindMarked(); - - titleInfo->fBitrate = fVideoSlider->Value(); - audio1Info->fOutBitrate = fAudioSlider->Value(); - audio2Info->fOutBitrate = fAudioSlider->Value(); - - fManager->Start( volumeInfo, titleInfo, - audio1Info, audio2Info, - (char*) fFileControl->Text() ); - - /* Update the button label */ - if( Lock() ) - { - fStartButton->SetLabel( "Cancel" ); - fStartButton->SetMessage( new BMessage( STOP_CONVERT ) ); - Unlock(); - } - break; - } - - case STOP_CONVERT: - /* Stop the job */ - fManager->Cancel(); - - /* Update the button label */ - if( Lock() ) - { - fStartButton->SetLabel( "Start !" ); - fStartButton->SetMessage( new BMessage( START_CONVERT ) ); - Unlock(); - } - - /* Enable the interface */ - Status( "Cancelled.", 0.0, ENABLE_READY ); - break; - - case REFRESH_VOLUMES: - /* Disable the interface */ - Status( "Checking DVD volumes...", 0.0, ENABLE_DETECTING ); - - /* Ask the manager to start the detection */ - fManager->PostMessage( DETECT_VOLUMES ); - break; - - case VOLUMES_DETECTED: - { - /* Update the popup */ - BList * volumeList; - message->FindPointer( "list", (void**)&volumeList ); - RefreshVolumes( volumeList ); - - /* Enable the interface */ - Status( "Ready.", 0.0, ENABLE_READY ); - break; - } - - case B_ABOUT_REQUESTED: - { - BAlert * alert; - alert = new BAlert( "title", - "HandBrake " VERSION "\n\n" - "by Eric Petit <[email protected]>\n" - "Homepage : <http://beos.titer.org/handbrake/>\n\n" - "No, you don't want to know where this stupid app " - "name comes from.", - "Woot !" ); - alert->Go( NULL ); - break; - } - - case MANAGER_CREATED: - { - message->FindPointer( "manager", (void**)&fManager ); - break; - } - - case CHANGE_STATUS: - { - char * text; - float pos; - int mode; - message->FindPointer( "text", (void**) &text ); - message->FindFloat( "pos", &pos ); - message->FindInt32( "mode", (int32*) &mode ); - - if( !Lock() ) - { - Log( "HBWindow::MessageReceived() : Lock() failed" ); - break; - } - fStatusBar->Update( pos - fStatusBar->CurrentValue(), text ); - Enable( mode ); - Unlock(); - - free( text ); - - break; - } - - default: - { - BWindow::MessageReceived( message ); - } - } -} - -void HBWindow::Enable( int mode ) -{ - switch( mode ) - { - case ENABLE_DETECTING: - fVolumeField->SetEnabled( false ); - fTitleField->SetEnabled( false ); - fAudio1Field->SetEnabled( false ); - fAudio2Field->SetEnabled( false ); - fVideoSlider->SetEnabled( true ); - fAudioSlider->SetEnabled( true ); - fFileControl->SetEnabled( true ); - fAdvancedButton->SetEnabled( true ); - fFileString->SetHighColor( 0, 0, 0 ); - fFileString->Invalidate(); - fPictureButton->SetEnabled( false ); - fRefreshButton->SetEnabled( false ); - fSuspendButton->SetEnabled( false ); - fStartButton->SetEnabled( false ); - break; - - case ENABLE_READY: - fVolumeField->SetEnabled( true ); - fTitleField->SetEnabled( true ); - fAudio1Field->SetEnabled( true ); - fAudio2Field->SetEnabled( true ); - fVideoSlider->SetEnabled( true ); - fAudioSlider->SetEnabled( true ); - fFileControl->SetEnabled( true ); - fAdvancedButton->SetEnabled( true ); - fFileString->SetHighColor( 0, 0, 0 ); - fFileString->Invalidate(); - fPictureButton->SetEnabled( true ); - fRefreshButton->SetEnabled( true ); - fSuspendButton->SetEnabled( false ); - fStartButton->SetEnabled( true ); - break; - - case ENABLE_ENCODING: - fVolumeField->SetEnabled( false ); - fTitleField->SetEnabled( false ); - fAudio1Field->SetEnabled( false ); - fAudio2Field->SetEnabled( false ); - fVideoSlider->SetEnabled( false ); - fAudioSlider->SetEnabled( false ); - fFileControl->SetEnabled( false ); - fAdvancedButton->SetEnabled( false ); - fFileString->SetHighColor( 156, 156, 156 ); - fFileString->Invalidate(); - fPictureButton->SetEnabled( false ); - fRefreshButton->SetEnabled( false ); - fSuspendButton->SetEnabled( true ); - fStartButton->SetEnabled( true ); - break; - } -} - -void HBWindow::RefreshVolumes( BList * volumeList ) -{ - if( !( Lock() ) ) - { - Log( "HBWindow::RefreshVolumes : Lock() failed" ); - return; - } - - /* Empty the PopUps */ - HBVolumeInfo * volumeInfo; - while( ( volumeInfo = (HBVolumeInfo*) fVolumePopUp->ItemAt( 0 ) ) ) - { - fVolumePopUp->RemoveItem( volumeInfo ); - } - - HBTitleInfo * titleInfo; - while( ( titleInfo = (HBTitleInfo*) fTitlePopUp->ItemAt( 0 ) ) ) - { - fTitlePopUp->RemoveItem( titleInfo ); - } - - HBAudioInfo * audioInfo; - while( ( audioInfo = (HBAudioInfo*) fAudio1PopUp->ItemAt( 0 ) ) ) - { - fAudio1PopUp->RemoveItem( audioInfo ); - } - while( ( audioInfo = (HBAudioInfo*) fAudio2PopUp->ItemAt( 0 ) ) ) - { - fAudio2PopUp->RemoveItem( audioInfo ); - } - - /* Fill the Volumes PopUp */ - for( int i = 0; i < volumeList->CountItems(); i++ ) - { - fVolumePopUp->AddItem( (HBVolumeInfo*) volumeList->ItemAt( i ) ); - } - - /* Select the first volume */ - if( !( volumeInfo = (HBVolumeInfo*) volumeList->ItemAt( 0 ) ) ) - { - Log( "HBWindow::RefreshVolumes : no volume found" ); - Unlock(); - return; - } - volumeInfo->SetMarked( true ); - - /* Fill the Titles PopUp */ - BList * titleList = volumeInfo->fTitleList; - for( int i = 0; i < titleList->CountItems(); i++ ) - { - fTitlePopUp->AddItem( (HBTitleInfo*) titleList->ItemAt( i ) ); - } - - /* Select the first title */ - if( !( titleInfo = (HBTitleInfo*) titleList->ItemAt( 0 ) ) ) - { - Log( "HBWindow::RefreshVolumes : no title found" ); - Unlock(); - return; - } - titleInfo->SetMarked( true ); - - /* Fill the Audios PopUp */ - BList * audioList1 = titleInfo->fAudioInfoList1; - BList * audioList2 = titleInfo->fAudioInfoList2; - for( int i = 0; i < audioList1->CountItems(); i++ ) - { - fAudio1PopUp->AddItem( (HBAudioInfo*) audioList1->ItemAt( i ) ); - fAudio2PopUp->AddItem( (HBAudioInfo*) audioList2->ItemAt( i ) ); - } - - audioInfo = (HBAudioInfo*) fAudio1PopUp->ItemAt( 0 ); - audioInfo->SetMarked( true ); - audioInfo = (HBAudioInfo*) fAudio2PopUp->ItemAt( fAudio2PopUp->CountItems() - 1 ); - audioInfo->SetMarked( true ); - - Unlock(); -} - -void HBWindow::SelectionChanged() -{ - HBVolumeInfo * volumeInfo; - HBTitleInfo * titleInfo; - HBAudioInfo * audioInfo; - - /* Update the Title popup if needed */ - bool updateTitlePopUp = true; - volumeInfo = (HBVolumeInfo*) fVolumePopUp->FindMarked(); - titleInfo = (HBTitleInfo*) fTitlePopUp->FindMarked(); - - for( int i = 0; i < volumeInfo->fTitleList->CountItems(); i++ ) - { - if( titleInfo == volumeInfo->fTitleList->ItemAt( i ) ) - { - /* No need to update titles, we already are on the right - volume */ - updateTitlePopUp = false; - break; - } - } - - if( updateTitlePopUp ) - { - /* Empty the popup */ - while( ( titleInfo = (HBTitleInfo*) fTitlePopUp->ItemAt( 0 ) ) ) - { - fTitlePopUp->RemoveItem( titleInfo ); - } - - /* Fill it */ - for( int i = 0; i < volumeInfo->fTitleList->CountItems(); i++ ) - { - fTitlePopUp->AddItem( (HBTitleInfo*) volumeInfo->fTitleList->ItemAt( i ) ); - } - - /* Select the first title */ - ((HBTitleInfo*) fTitlePopUp->ItemAt( 0 ))->SetMarked( true ); - } - - /* Update the Audio popups if needed */ - bool updateAudioPopUp = true; - titleInfo = (HBTitleInfo*) fTitlePopUp->FindMarked(); - audioInfo = (HBAudioInfo*) fAudio1PopUp->FindMarked(); - - for( int i = 0; i < titleInfo->fAudioInfoList1->CountItems(); i++ ) - { - if( audioInfo == titleInfo->fAudioInfoList1->ItemAt( i ) ) - { - /* No need to update audio, we already are on the right - title */ - updateAudioPopUp = false; - break; - } - } - - if( updateAudioPopUp ) - { - /* Empty the popups */ - while( ( audioInfo = (HBAudioInfo*) fAudio1PopUp->ItemAt( 0 ) ) ) - { - fAudio1PopUp->RemoveItem( audioInfo ); - } - while( ( audioInfo = (HBAudioInfo*) fAudio2PopUp->ItemAt( 0 ) ) ) - { - fAudio2PopUp->RemoveItem( audioInfo ); - } - - /* Fill it */ - for( int i = 0; i < titleInfo->fAudioInfoList1->CountItems(); i++ ) - { - fAudio1PopUp->AddItem( (HBAudioInfo*) titleInfo->fAudioInfoList1->ItemAt( i ) ); - fAudio2PopUp->AddItem( (HBAudioInfo*) titleInfo->fAudioInfoList2->ItemAt( i ) ); - } - - /* Select the first track */ - ((HBAudioInfo*) fAudio1PopUp->ItemAt( 0 ))->SetMarked( true ); - - /* Select "None" */ - ((HBAudioInfo*) fAudio2PopUp->ItemAt( fAudio2PopUp->CountItems() - 1 ))->SetMarked( true ); - } - -} diff --git a/HBWindow.h b/HBWindow.h deleted file mode 100644 index 73aa895b3..000000000 --- a/HBWindow.h +++ /dev/null @@ -1,62 +0,0 @@ -/* $Id: HBWindow.h,v 1.8 2003/08/24 19:28:18 titer Exp $ */ - -#ifndef _HB_WINDOW_H -#define _HB_WINDOW_H - -#include <Box.h> -#include <Window.h> - -class HBManager; - -class BButton; -class BMenuField; -class BPopUpMenu; -class BSlider; -class BStatusBar; -class BStringView; -class BTextControl; - -class HBBox : public BBox -{ - public: - HBBox( BRect ); - virtual void Draw( BRect ); -}; - -class HBWindow : public BWindow -{ - public: - HBWindow(); - virtual bool QuitRequested(); - virtual void MessageReceived( BMessage * message ); - - void RefreshVolumes( BList * volumeList ); - - private: - void Enable( int mode ); - void SelectionChanged(); - - HBManager * fManager; - HBBox * fBox; - BMenuField * fVolumeField; - BPopUpMenu * fVolumePopUp; - BMenuField * fTitleField; - BPopUpMenu * fTitlePopUp; - BMenuField * fAudio1Field; - BPopUpMenu * fAudio1PopUp; - BMenuField * fAudio2Field; - BPopUpMenu * fAudio2PopUp; - BSlider * fVideoSlider; - BSlider * fAudioSlider; - BStringView * fFileString; - BTextControl * fFileControl; - BButton * fFileButton; - BButton * fPictureButton; - BButton * fAdvancedButton; - BStatusBar * fStatusBar; - BButton * fRefreshButton; - BButton * fSuspendButton; - BButton * fStartButton; -}; - -#endif diff --git a/HandBrake.cpp b/HandBrake.cpp deleted file mode 100644 index 91a2628b4..000000000 --- a/HandBrake.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* $Id: HandBrake.cpp,v 1.1.1.1 2003/06/24 13:43:48 titer Exp $ */ - -#include "HBApp.h" - -#include <ffmpeg/avcodec.h> - -int main() -{ - /* libavcodec initializations */ - avcodec_init(); - register_avcodec( &mpeg4_encoder ); - - /* Run the BApplication */ - HBApp * app = new HBApp(); - app->Run(); - delete app; - return 0; -} @@ -1,14 +1,86 @@ -# $Id: Jamfile,v 1.17 2003/08/26 18:54:06 titer Exp $ +# $Id: Jamfile,v 1.33 2003/10/06 21:21:27 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. -HB_VERSION = 0.2 ; +HB_VERSION = 0.3 ; -C++FLAGS = $(CPPFLAGS) ; -C++FLAGS += -g -Wall -Werror -Wno-multichar -O3 -funroll-loops ; -C++FLAGS += -DVERSION=\\\"$(HB_VERSION)\\\" ; -LINKFLAGS = $(LDFLAGS) ; -LINKLIBS = -lbe -ldvdplay -ldvdread -ldvdcss -lmpeg2 -lavcodec -la52 -lmp3lame ; +# Compilers +C++ = g++ ; +LINK = g++ ; + +# Flags +C++FLAGS = $(CPPFLAGS) ; +C++FLAGS += -g -Wall -Werror ; +C++FLAGS += -DVERSION=\\\"$(HB_VERSION)\\\" -DSYS_$(OS) ; +LINKFLAGS = $(LDFLAGS) ; +HDRS = core ; + +# Optims +C++FLAGS += -funroll-loops ; +OPTIM = -O3 ; + +# Libs +LINKLIBS = -ldvdplay -ldvdread -ldvdcss -lmpeg2 -lavcodec -la52 -lmp3lame ; + +# OS specific +if $(OS) = BEOS +{ + C++FLAGS += -Wno-multichar ; + LINKLIBS += -lbe ; +} +else if $(OS) = LINUX +{ + LINKLIBS += -lpthread ; +} +else if $(OS) = MACOSX +{ + # needed to clean HandBrake.app + RM = rm -rf ; +} + +# Do not remove temporary object files +# There MUST be a cleaner way to do this +actions quietly updated piecemeal together RmTemps +{ +} + +# Build HandBrake.app using ProjectBuilder +rule OSXApp +{ + Clean clean : $(1) ; + BuildOSXApp $(1) ; +} + +actions BuildOSXApp +{ + $(RM) HandBrake.app ; + ( cd macosx && pbxbuild ) && mv macosx/build/HandBrake.app . ; + $(RM) macosx/build ; +} + +Library core/libhb : core/Ac3Decoder.cpp core/AviMuxer.cpp + core/Common.cpp core/DVDReader.cpp core/Fifo.cpp + core/Manager.cpp core/Mp3Encoder.cpp + core/Mpeg2Decoder.cpp core/Mpeg4Encoder.cpp + core/MpegDemux.cpp core/Resizer.cpp + core/Scanner.cpp core/Thread.cpp ; + +LinkLibraries HBTest : core/libhb.a ; +Main HBTest : test/Test.cpp ; + +if $(OS) = BEOS +{ + LinkLibraries HandBrake : core/libhb.a ; + Main HandBrake : beos/HandBrake.cpp beos/MainWindow.cpp + beos/PictureWin.cpp ; +} + +if $(OS) = MACOSX +{ + OSXApp HandBrake.app ; + Depends HandBrake.app : core/libhb.a ; + Depends all : HandBrake.app ; +} -Main HandBrake : - HandBrake.cpp HBAc3Decoder.cpp HBApp.cpp HBAviMuxer.cpp HBCommon.cpp - HBDVDReader.cpp HBFifo.cpp HBManager.cpp HBMp3Encoder.cpp HBMpeg2Decoder.cpp - HBMpeg4Encoder.cpp HBMpegDemux.cpp HBPictureWin.cpp HBThread.cpp HBWindow.cpp ; @@ -1,7 +1,13 @@ -$Id: NEWS,v 1.6 2003/08/26 18:54:06 titer Exp $ +$Id: NEWS,v 1.9 2003/10/06 21:21:27 titer Exp $ + +Changes between 0.2 and 0.3 + - OSX & Linux ports + - Allow 2-pass encoding + - Many internal changes & fixes Changes between 0.1.1 and 0.2 - - Fixed a major bug that made HandBrake probably crash after ~ 15 minutes encoded + - Fixed a major bug that made HandBrake probably crash after ~ 15 + minutes encoded - Fixed a few minor memory leaks Changes between 0.1 and 0.1.1 @@ -21,4 +27,4 @@ Changes between 0.1-alpha and 0.1-alpha2 : - Fixed the screwed-audio bug - Many bugfixes... -First version is 0.1-alpha.
\ No newline at end of file +First version is 0.1-alpha. @@ -0,0 +1,10 @@ +- General + + Keep detecting DVDs after launching + + Possible to specify a target size + + Use the DVD name in popup and for the name of the created file + + Show the current pass + +- OSX port + + Check thread priorities + + "Ding" when done + window + "Ahuh" + + Preview in a drawer diff --git a/beos/HandBrake.cpp b/beos/HandBrake.cpp new file mode 100644 index 000000000..b1b386a6d --- /dev/null +++ b/beos/HandBrake.cpp @@ -0,0 +1,52 @@ +/* $Id: HandBrake.cpp,v 1.6 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 <signal.h> + +#include "HandBrake.h" +#include "MainWindow.h" + +void SigHandler( int signal ) +{ + ((HBApp*) be_app)->fWindow->PostMessage( B_QUIT_REQUESTED ); +} + +int main( int argc, char ** argv ) +{ + signal( SIGINT, SigHandler ); + signal( SIGHUP, SigHandler ); + signal( SIGQUIT, SigHandler ); + + int c; + bool debug = false; + while( ( c = getopt( argc, argv, "v" ) ) != -1 ) + { + switch( c ) + { + case 'v': + debug = true; + break; + + default: + break; + } + } + + /* Run the BApplication */ + HBApp * app = new HBApp( debug ); + app->Run(); + delete app; + return 0; +} + +/* Constructor */ +HBApp::HBApp( bool debug ) + : BApplication( "application/x-vnd.titer-handbrake" ) +{ + fWindow = new HBWindow( debug ); + fWindow->Show(); +} + diff --git a/beos/HandBrake.h b/beos/HandBrake.h new file mode 100644 index 000000000..72234e195 --- /dev/null +++ b/beos/HandBrake.h @@ -0,0 +1,22 @@ +/* $Id: HandBrake.h,v 1.5 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. */ + +#ifndef HB_HANDBRAKE_H +#define HB_HANDBRAKE_H + +#include <Application.h> + +class HBWindow; + +class HBApp : public BApplication +{ + public: + HBApp( bool debug ); + + HBWindow * fWindow; +}; + +#endif diff --git a/beos/MainWindow.cpp b/beos/MainWindow.cpp new file mode 100644 index 000000000..ca18537a5 --- /dev/null +++ b/beos/MainWindow.cpp @@ -0,0 +1,759 @@ +/* $Id: MainWindow.cpp,v 1.14 2003/10/05 14:56:38 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 <fs_info.h> +#include <sys/ioctl.h> +#include <Alert.h> +#include <Application.h> +#include <Box.h> +#include <Button.h> +#include <Directory.h> +#include <Drivers.h> +#include <MenuField.h> +#include <Path.h> +#include <Query.h> +#include <PopUpMenu.h> +#include <Screen.h> +#include <Slider.h> +#include <StatusBar.h> +#include <StringView.h> +#include <TextControl.h> +#include <VolumeRoster.h> + +#include "MainWindow.h" +#include "Manager.h" +#include "PictureWin.h" + +#define DEFAULT_FILE "/boot/home/Desktop/Movie.avi" +#define WINDOW_RECT BRect( 0,0,400,405 ) + +#define BUTTON_ADVANCED 'badv' +#define BUTTON_FILE 'bfil' +#define BUTTON_PICTURE 'bpic' +#define BUTTON_START 'bsta' +#define BUTTON_CANCEL 'bcan' +#define BUTTON_SUSPEND 'bsus' +#define BUTTON_RESUME 'bres' +#define POPUP_AUDIO 'paud' +#define POPUP_TITLE 'ptit' +#define POPUP_VOLUME 'pvol' +#define SLIDER_AUDIO 'saud' +#define SLIDER_VIDEO 'svid' + +/* HBBox : almost a simple BBox, unless we draw a horizontal line + before the "Picture" and "Advanced" buttons. There must be a + cleaner way to do this, but I'm not a expert GUI programmer. */ + +/* Constructor */ +HBBox::HBBox( BRect rect ) + : BBox( rect, NULL ) +{ +} + +/* Draw */ +void HBBox::Draw( BRect rect ) +{ + /* Inherited method */ + BBox::Draw( rect ); + + /* Draw the line */ + SetHighColor( 120, 120, 120 ); + SetLowColor( 255, 255, 255 ); + StrokeLine( BPoint( 10, 265 ), + BPoint( Bounds().Width() - 10, 265 ), + B_SOLID_HIGH ); + StrokeLine( BPoint( 11, 266 ), + BPoint( Bounds().Width() - 10, 266 ), + B_SOLID_LOW ); +} + +HBVolumeItem::HBVolumeItem( HBVolume * volume ) + : BMenuItem( "", new BMessage( POPUP_VOLUME ) ) +{ + fVolume = volume; + + SetLabel( fVolume->fName ); +} + +HBTitleItem::HBTitleItem( HBTitle * title ) + : BMenuItem( "", new BMessage( POPUP_TITLE) ) +{ + fTitle = title; + + char label[1024]; memset( label, 0, 1024 ); + sprintf( label, "%d (%02lld:%02lld:%02lld)", fTitle->fIndex, + fTitle->fLength / 3600, ( fTitle->fLength % 3600 ) / 60, + fTitle->fLength % 60 ); + SetLabel( label ); +} + +HBAudioItem::HBAudioItem( HBAudio * audio ) + : BMenuItem( "", new BMessage( POPUP_AUDIO ) ) +{ + fAudio = audio; + + SetLabel( fAudio ? fAudio->fDescription : "None" ); +} + +HBWindow::HBWindow( bool debug ) + : BWindow( WINDOW_RECT, "HandBrake " VERSION, B_TITLED_WINDOW, + B_NOT_RESIZABLE | B_NOT_ZOOMABLE ) +{ + /* Center the window */ + BScreen screen; + MoveTo( ( screen.Frame().Width() - Frame().Width() ) / 2, + ( screen.Frame().Height() - Frame().Height() ) / 2 ); + + /* -- GUI starts here -- */ + + BRect r; + + /* Add a background view */ + BView * view; + view = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW ); + view->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); + + /* Add the settings box */ + r = BRect( 10, 10, view->Bounds().Width() - 10, + view->Bounds().Height() - 85 ); + fBox = new HBBox( r ); + fBox->SetLabel( "Settings" ); + + /* Volume */ + r = BRect( 10, 15, fBox->Bounds().Width() - 10, 35 ); + fVolumePopUp = new BPopUpMenu( "" ); + fVolumeField = new BMenuField( r, NULL, "Volume :", + fVolumePopUp, true ); + fBox->AddChild( fVolumeField ); + + /* Title */ + r = BRect( 10, 45, fBox->Bounds().Width() - 10, 65 ); + fTitlePopUp = new BPopUpMenu( "" ); + fTitleField = new BMenuField( r, NULL, "Title :", + fTitlePopUp, true ); + fBox->AddChild( fTitleField ); + + /* Audio 1 */ + r = BRect( 10, 75, fBox->Bounds().Width() - 10, 95 ); + fAudio1PopUp = new BPopUpMenu( "" ); + fAudio1Field = new BMenuField( r, NULL, "Audio 1 :", + fAudio1PopUp, true ); + fBox->AddChild( fAudio1Field ); + + /* Audio 2 */ + r = BRect( 10, 105, fBox->Bounds().Width() - 10, 125 ); + fAudio2PopUp = new BPopUpMenu( "" ); + fAudio2Field = new BMenuField( r, NULL, "Audio 2 :", + fAudio2PopUp, true ); + fBox->AddChild( fAudio2Field ); + + /* Video bitrate */ + r = BRect( 10, 135, fBox->Bounds().Width() - 10, 165 ); + fVideoSlider = new BSlider( r, NULL, "Video bitrate : 1024 kbps", + new BMessage( SLIDER_VIDEO ), + 128, 4096, B_TRIANGLE_THUMB ); + fVideoSlider->SetValue( 1024 ); + fBox->AddChild( fVideoSlider ); + + /* Audio bitrate */ + r = BRect( 10, 175, fBox->Bounds().Width() - 10, 205 ); + fAudioSlider = new BSlider( r, NULL, "Audio bitrate : 128 kbps", + new BMessage( SLIDER_AUDIO ), + 64, 384, B_TRIANGLE_THUMB ); + fAudioSlider->SetValue( 128 ); + fBox->AddChild( fAudioSlider ); + + /* Destination file */ + r = BRect( 10, 215, fBox->Bounds().Width() - 10, 230 ); + fFileString = new BStringView( r, NULL, "Destination file :" ); + fBox->AddChild( fFileString ); + r = BRect( 10, 235, fBox->Bounds().Width() - 90, 255 ); + fFileControl = new BTextControl( r, NULL, "", DEFAULT_FILE, + new BMessage() ); + fFileControl->SetDivider( 0 ); + fBox->AddChild( fFileControl ); + r = BRect( fBox->Bounds().Width() - 80, 230, + fBox->Bounds().Width() - 10, 255 ); + fFileButton = new BButton( r, NULL, "Browse...", + new BMessage( BUTTON_FILE ) ); + fBox->AddChild( fFileButton ); + + /* Settings buttons */ + r = BRect( fBox->Bounds().Width() - 200, 275, + fBox->Bounds().Width() - 100, 300 ); + fPictureButton = new BButton( r, NULL, "Picture settings...", + new BMessage( BUTTON_PICTURE ) ); + fBox->AddChild( fPictureButton ); + + r = BRect( fBox->Bounds().Width() - 90, 275, + fBox->Bounds().Width() - 10, 300 ); + fAdvancedButton = new BButton( r, NULL, "Advanced...", + new BMessage( BUTTON_ADVANCED ) ); + fBox->AddChild( fAdvancedButton ); + + view->AddChild( fBox ); + + /* Status bar */ + r = BRect( 10, view->Bounds().Height() - 75, + view->Bounds().Width() - 10, view->Bounds().Height() - 45 ); + fStatusBar = new BStatusBar( r, NULL, NULL ); + fStatusBar->SetMaxValue( 1.0 ); + view->AddChild( fStatusBar ); + + /* Buttons */ + r = BRect( view->Bounds().Width() - 240, view->Bounds().Height() - 35, + view->Bounds().Width() - 170, view->Bounds().Height() - 10 ); + BButton * aboutButton; + aboutButton = new BButton( r, NULL, "About...", + new BMessage( B_ABOUT_REQUESTED ) ); + view->AddChild( aboutButton ); + + r = BRect( view->Bounds().Width() - 160, view->Bounds().Height() - 35, + view->Bounds().Width() - 90, view->Bounds().Height() - 10 ); + fSuspendButton = new BButton( r, NULL, "Suspend", + new BMessage( BUTTON_SUSPEND ) ); + view->AddChild( fSuspendButton ); + + r = BRect( view->Bounds().Width() - 80, view->Bounds().Height() - 35, + view->Bounds().Width() - 10, view->Bounds().Height() - 10 ); + fStartButton = new BButton( r, NULL, "Start !", + new BMessage( BUTTON_START ) ); + view->AddChild( fStartButton ); + + AddChild( view ); + + /* -- GUI ends here -- */ + + /* Init libhb & launch the manager thread */ + fManager = new HBManager( debug ); + + /* Detects DVD drives & VOB folders, then tell libhb to scan it */ + ScanVolumes(); + + /* Update the interface */ + fUpdateThread = spawn_thread( (int32 (*)(void *)) UpdateInterface, + "interface", B_DISPLAY_PRIORITY, this ); + resume_thread( fUpdateThread ); +} + +bool HBWindow::QuitRequested() +{ + /* Clean up */ + kill_thread( fUpdateThread ); + delete fManager; + + /* Stop the application */ + be_app->PostMessage( B_QUIT_REQUESTED ); + return true; +} + +void HBWindow::MessageReceived( BMessage * message ) +{ + switch( message->what ) + { + case B_ABOUT_REQUESTED: + { + BAlert * alert; + alert = new BAlert( "About HandBrake", + "HandBrake " VERSION "\n\n" + "by Eric Petit <[email protected]>\n" + "Homepage : <http://beos.titer.org/handbrake/>\n\n" + "No, you don't want to know where this stupid app " + "name comes from.\n\n" + "Thanks to BGA for pointing out very cool bugs ;)", + "Woot !" ); + alert->Go( NULL ); + break; + } + + case BUTTON_ADVANCED: + break; + + case BUTTON_FILE: + break; + + case BUTTON_PICTURE: + { + HBTitle * title = + ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle; + HBPictureWin * pictureWin = new HBPictureWin( fManager, title ); + pictureWin->Show(); + break; + } + + case BUTTON_START: + { + HBTitle * title = + ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle; + HBAudio * audio1 = + ((HBAudioItem*) fAudio1PopUp->FindMarked())->fAudio; + HBAudio * audio2 = + ((HBAudioItem*) fAudio2PopUp->FindMarked())->fAudio; + + title->fBitrate = fVideoSlider->Value(); + if( audio1 ) + { + audio1->fOutBitrate = fAudioSlider->Value(); + } + if( audio2 ) + { + audio2->fOutBitrate = fAudioSlider->Value(); + } + + fManager->StartRip( title, audio1, audio2, + (char*) fFileControl->Text() ); + break; + } + + case BUTTON_CANCEL: + fManager->StopRip(); + break; + + case BUTTON_SUSPEND: + fManager->SuspendRip(); + break; + + case BUTTON_RESUME: + fManager->ResumeRip(); + break; + + case POPUP_AUDIO: + break; + + case POPUP_TITLE: + { + HBTitle * title = + ((HBTitleItem*) fTitlePopUp->FindMarked())->fTitle; + + /* Empty audio popups */ + HBAudioItem * audioItem; + while( ( audioItem = (HBAudioItem*) fAudio1PopUp->ItemAt( 0 ) ) ) + { + fAudio1PopUp->RemoveItem( audioItem ); + delete audioItem; + } + while( ( audioItem = (HBAudioItem*) fAudio2PopUp->ItemAt( 0 ) ) ) + { + fAudio2PopUp->RemoveItem( audioItem ); + delete audioItem; + } + + HBAudio * audio; + for( uint32_t i = 0; + i < title->fAudioList->CountItems(); + i++ ) + { + audio = (HBAudio*) title->fAudioList->ItemAt( i ); + fAudio1PopUp->AddItem( new HBAudioItem( audio ) ); + fAudio2PopUp->AddItem( new HBAudioItem( audio ) ); + } + fAudio1PopUp->AddItem( new HBAudioItem( NULL ) ); + fAudio2PopUp->AddItem( new HBAudioItem( NULL ) ); + ((HBAudioItem*) fAudio1PopUp->ItemAt( 0 ))->SetMarked( true ); + ((HBAudioItem*) fAudio2PopUp->ItemAt( + fAudio2PopUp->CountItems() - 1 ))->SetMarked( true ); + + break; + } + + case POPUP_VOLUME: + break; + + case SLIDER_AUDIO: + { + char label[64]; memset( label, 0, 64 ); + snprintf( label, 128, "Audio bitrate : %ld kbps", + fAudioSlider->Value() ); + fAudioSlider->SetLabel( label ); + break; + } + + case SLIDER_VIDEO: + { + char label[64]; memset( label, 0, 64 ); + snprintf( label, 128, "Video bitrate : %ld kbps", + fVideoSlider->Value() ); + fVideoSlider->SetLabel( label ); + break; + } + + default: + BWindow::MessageReceived( message ); + break; + } +} + + +void HBWindow::ScanVolumes() +{ + BVolumeRoster * roster = new BVolumeRoster(); + BVolume * bVolume = new BVolume(); + fs_info info; + int device; + device_geometry geometry; + + HBVolume * volume; + HBList * volumeList = new HBList(); + + /* Parse mounted volumes */ + while( roster->GetNextVolume( bVolume ) == B_NO_ERROR ) + { + /* open() and ioctl() for more informations */ + fs_stat_dev( bVolume->Device(), &info ); + if( ( device = open( info.device_name, O_RDONLY ) ) < 0 ) + { + continue; + } + + if( ioctl( device, B_GET_GEOMETRY, &geometry, + sizeof( geometry ) ) < 0 ) + + { + continue; + } + + /* Get the volume name */ + char volumeName[B_FILE_NAME_LENGTH]; + bVolume->GetName( volumeName ); + + if( bVolume->IsReadOnly() && geometry.device_type == B_CD ) + { + /* May be a DVD */ + volume = new HBVolume( info.device_name, volumeName ); + volumeList->AddItem( volume ); + } + else if( geometry.device_type == B_DISK ) + { + /* May be a hard drive. Look for VIDEO_TS folders on it */ + BQuery * query = new BQuery(); + + if( query->SetVolume( bVolume ) != B_OK ) + { + delete query; + continue; + } + + if( query->SetPredicate( "name = VIDEO_TS.BUP" ) != B_OK ) + { + delete query; + continue; + } + + query->Fetch(); + + BEntry entry, parentEntry; + BPath path; + while( query->GetNextEntry( &entry ) == B_OK ) + { + entry.GetParent( &parentEntry ); + parentEntry.GetPath( &path ); + + volume = new HBVolume( (char*) path.Path() ); + volumeList->AddItem( volume ); + } + + delete query; + } + } + + fManager->ScanVolumes( volumeList ); +} + +void HBWindow::UpdateInterface( HBWindow * _this ) +{ + for( ;; ) + { + _this->_UpdateInterface(); + snooze( 10000 ); + } +} + +void HBWindow::_UpdateInterface() +{ + if( !fManager->NeedUpdate() ) + { + return; + } + + HBStatus status = fManager->GetStatus(); + + if( !Lock() ) + { + fprintf( stderr, "Lock() failed\n" ); + return; + } + + EnableInterface( status.fMode ); + + switch( status.fMode ) + { + case HB_MODE_UNDEF: + break; + + case HB_MODE_SCANNING: + { + char text[1024]; memset( text, 0, 1024 ); + sprintf( text, "Scanning %s, title %d...", + status.fScannedVolume, status.fScannedTitle ); + fStatusBar->Update( - fStatusBar->CurrentValue(), text ); + break; + } + + case HB_MODE_SCANDONE: + { + HBVolume * volume; + for( uint32_t i = 0; + i < status.fVolumeList->CountItems(); + i++ ) + { + volume = (HBVolume*) status.fVolumeList->ItemAt( i ); + fVolumePopUp->AddItem( new HBVolumeItem( volume ) ); + } + ((HBVolumeItem*) fVolumePopUp->ItemAt( 0 ))->SetMarked( true ); + + HBTitle * title; + volume = (HBVolume*) status.fVolumeList->ItemAt( 0 ); + for( uint32_t i = 0; + i < volume->fTitleList->CountItems(); + i++ ) + { + title = (HBTitle*) volume->fTitleList->ItemAt( i ); + fTitlePopUp->AddItem( new HBTitleItem( title ) ); + } + ((HBTitleItem*) fTitlePopUp->ItemAt( 0 ))->SetMarked( true ); + + HBAudio * audio; + title = (HBTitle*) volume->fTitleList->ItemAt( 0 ); + for( uint32_t i = 0; + i < title->fAudioList->CountItems(); + i++ ) + { + audio = (HBAudio*) title->fAudioList->ItemAt( i ); + fAudio1PopUp->AddItem( new HBAudioItem( audio ) ); + fAudio2PopUp->AddItem( new HBAudioItem( audio ) ); + } + fAudio1PopUp->AddItem( new HBAudioItem( NULL ) ); + fAudio2PopUp->AddItem( new HBAudioItem( NULL ) ); + ((HBAudioItem*) fAudio1PopUp->ItemAt( 0 ))->SetMarked( true ); + ((HBAudioItem*) fAudio2PopUp->ItemAt( + fAudio2PopUp->CountItems() - 1 ))->SetMarked( true ); + + fStatusBar->Update( - fStatusBar->CurrentValue(), + "Ready. Press 'Start' to rip." ); + break; + } + + case HB_MODE_ENCODING: + { + char text[1024]; memset( text, 0, 1024 ); + sprintf( text, + "Encoding : %.2f %%, %.2f fps (%02d:%02d:%02d remaining)", + 100 * status.fPosition, status.fFrameRate, + status.fRemainingTime / 3600, + ( status.fRemainingTime % 3600 ) / 60, + status.fRemainingTime % 60 ); + fStatusBar->Update( status.fPosition - + fStatusBar->CurrentValue(), text ); + break; + } + + case HB_MODE_SUSPENDED: + { + char text[1024]; memset( text, 0, 1024 ); + sprintf( text, "Encoding : %.2f %%, %.2f fps (Paused)", + 100 * status.fPosition, status.fFrameRate ); + fStatusBar->Update( status.fPosition - + fStatusBar->CurrentValue(), text ); + break; + } + + case HB_MODE_DONE: + break; + + case HB_MODE_CANCELED: + break; + + case HB_MODE_ERROR: + break; + + default: + break; + } + + Unlock(); +} + +void HBWindow::EnableInterface( HBMode mode ) +{ + if( mode == fOldMode && mode != HB_MODE_UNDEF ) + { + return; + } + + switch( mode ) + { + case HB_MODE_UNDEF: + { + fAdvancedButton->SetEnabled( false ); + fFileButton->SetEnabled( false ); + fPictureButton->SetEnabled( false ); + fStartButton->SetEnabled( false ); + fSuspendButton->SetEnabled( false ); + fAudio1Field->SetEnabled( false ); + fAudio2Field->SetEnabled( false ); + fTitleField->SetEnabled( false ); + fVolumeField->SetEnabled( false ); + fAudioSlider->SetEnabled( false ); + fVideoSlider->SetEnabled( false ); + fFileString->SetHighColor( 156, 156, 156 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( false ); + break; + } + + case HB_MODE_SCANNING: + { + fAdvancedButton->SetEnabled( true ); + fFileButton->SetEnabled( true ); + fPictureButton->SetEnabled( false ); + fStartButton->SetEnabled( false ); + fSuspendButton->SetEnabled( false ); + fAudio1Field->SetEnabled( false ); + fAudio2Field->SetEnabled( false ); + fTitleField->SetEnabled( false ); + fVolumeField->SetEnabled( false ); + fAudioSlider->SetEnabled( true ); + fVideoSlider->SetEnabled( true ); + fFileString->SetHighColor( 0, 0, 0 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( true ); + break; + } + + case HB_MODE_SCANDONE: + { + fAdvancedButton->SetEnabled( true ); + fFileButton->SetEnabled( true ); + fPictureButton->SetEnabled( true ); + fStartButton->SetLabel( "Start" ); + fStartButton->SetMessage( new BMessage( BUTTON_START ) ); + fStartButton->SetEnabled( true ); + fSuspendButton->SetEnabled( false ); + fAudio1Field->SetEnabled( true ); + fAudio2Field->SetEnabled( true ); + fTitleField->SetEnabled( true ); + fVolumeField->SetEnabled( true ); + fAudioSlider->SetEnabled( true ); + fVideoSlider->SetEnabled( true ); + fFileString->SetHighColor( 0, 0, 0 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( true ); + break; + } + + case HB_MODE_ENCODING: + { + fFileButton->SetEnabled( false ); + fPictureButton->SetEnabled( false ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->SetMessage( new BMessage( BUTTON_CANCEL ) ); + fStartButton->SetEnabled( true ); + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetMessage( new BMessage( BUTTON_SUSPEND ) ); + fSuspendButton->SetEnabled( true ); + fAudio1Field->SetEnabled( false ); + fAudio2Field->SetEnabled( false ); + fTitleField->SetEnabled( false ); + fVolumeField->SetEnabled( false ); + fAudioSlider->SetEnabled( false ); + fVideoSlider->SetEnabled( false ); + fFileString->SetHighColor( 156, 156, 156 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( false ); + break; + } + + case HB_MODE_SUSPENDED: + { + fFileButton->SetEnabled( false ); + fPictureButton->SetEnabled( false ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->SetMessage( new BMessage( BUTTON_CANCEL ) ); + fStartButton->SetEnabled( true ); + fSuspendButton->SetLabel( "Resume" ); + fSuspendButton->SetMessage( new BMessage( BUTTON_RESUME ) ); + fSuspendButton->SetEnabled( true ); + fAudio1Field->SetEnabled( false ); + fAudio2Field->SetEnabled( false ); + fTitleField->SetEnabled( false ); + fVolumeField->SetEnabled( false ); + fAudioSlider->SetEnabled( false ); + fVideoSlider->SetEnabled( false ); + fFileString->SetHighColor( 156, 156, 156 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( false ); + break; + } + + case HB_MODE_DONE: + { + fFileButton->SetEnabled( false ); + fPictureButton->SetEnabled( false ); + fStartButton->SetEnabled( true ); + fSuspendButton->SetEnabled( true ); + fAudio1Field->SetEnabled( false ); + fAudio2Field->SetEnabled( false ); + fTitleField->SetEnabled( false ); + fVolumeField->SetEnabled( false ); + fAudioSlider->SetEnabled( false ); + fVideoSlider->SetEnabled( false ); + fFileString->SetHighColor( 156, 156, 156 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( false ); + break; + } + + case HB_MODE_CANCELED: + { + fFileButton->SetEnabled( false ); + fPictureButton->SetEnabled( false ); + fStartButton->SetEnabled( true ); + fSuspendButton->SetEnabled( true ); + fAudio1Field->SetEnabled( false ); + fAudio2Field->SetEnabled( false ); + fTitleField->SetEnabled( false ); + fVolumeField->SetEnabled( false ); + fAudioSlider->SetEnabled( false ); + fVideoSlider->SetEnabled( false ); + fFileString->SetHighColor( 156, 156, 156 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( false ); + break; + } + + case HB_MODE_ERROR: + { + fFileButton->SetEnabled( false ); + fPictureButton->SetEnabled( false ); + fStartButton->SetEnabled( true ); + fSuspendButton->SetEnabled( true ); + fAudio1Field->SetEnabled( false ); + fAudio2Field->SetEnabled( false ); + fTitleField->SetEnabled( false ); + fVolumeField->SetEnabled( false ); + fAudioSlider->SetEnabled( false ); + fVideoSlider->SetEnabled( false ); + fFileString->SetHighColor( 156, 156, 156 ); + fFileString->Invalidate(); + fFileControl->SetEnabled( false ); + break; + } + + default: + break; + } +} + diff --git a/beos/MainWindow.h b/beos/MainWindow.h new file mode 100644 index 000000000..e40c2587a --- /dev/null +++ b/beos/MainWindow.h @@ -0,0 +1,100 @@ +/* $Id: MainWindow.h,v 1.9 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. */ + + +#ifndef HB_MAIN_WINDOW_H +#define HB_MAIN_WINDOW_H + +/* BeOS headers */ +#include <Box.h> +#include <MenuItem.h> +#include <Window.h> +class BButton; +class BMenuField; +class BPopUpMenu; +class BSlider; +class BStatusBar; +class BStringView; +class BTextControl; + +/* libhb headers */ +#include "Manager.h" + +class HBVolumeItem : public BMenuItem +{ + public: + HBVolumeItem( HBVolume * volume ); + + HBVolume * fVolume; +}; + +class HBTitleItem : public BMenuItem +{ + public: + HBTitleItem( HBTitle * title ); + + HBTitle * fTitle; +}; + +class HBAudioItem : public BMenuItem +{ + public: + HBAudioItem( HBAudio * audio ); + + HBAudio * fAudio; +}; + +class HBBox : public BBox +{ + public: + HBBox( BRect ); + void Draw( BRect ); +}; + +class HBWindow : public BWindow +{ + public: + HBWindow( bool debug ); + virtual bool QuitRequested(); + virtual void MessageReceived( BMessage * message ); + + void ScanVolumes(); + + private: + static void UpdateInterface( HBWindow * _this ); + void _UpdateInterface(); + void EnableInterface( HBMode mode ); + + HBManager * fManager; + + /* GUI */ + HBBox * fBox; + BButton * fAdvancedButton; + BButton * fFileButton; + BButton * fPictureButton; + BButton * fStartButton; + BButton * fSuspendButton; + BMenuField * fAudio1Field; + BMenuField * fAudio2Field; + BMenuField * fTitleField; + BMenuField * fVolumeField; + BPopUpMenu * fAudio1PopUp; + BPopUpMenu * fAudio2PopUp; + BPopUpMenu * fTitlePopUp; + BPopUpMenu * fVolumePopUp; + BSlider * fAudioSlider; + BSlider * fVideoSlider; + BStatusBar * fStatusBar; + BStringView * fFileString; + BTextControl * fFileControl; + + int fUpdateThread; + + /* Used to SetEnabled() GUI items only if needed */ + HBMode fOldMode; +}; + +#endif diff --git a/beos/PictureWin.cpp b/beos/PictureWin.cpp new file mode 100644 index 000000000..23aabe7c6 --- /dev/null +++ b/beos/PictureWin.cpp @@ -0,0 +1,233 @@ +/* $Id: PictureWin.cpp,v 1.5 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 <Bitmap.h> +#include <Box.h> +#include <Button.h> +#include <CheckBox.h> +#include <Screen.h> +#include <Slider.h> + +#include "PictureWin.h" +#include "Manager.h" + +#define UPDATE_BITMAP 'upbi' + +/* Handy way to access HBTitle members */ +#define fInWidth fTitle->fInWidth +#define fInHeight fTitle->fInHeight +#define fPixelWidth fTitle->fPixelWidth +#define fPixelHeight fTitle->fPixelHeight +#define fDeinterlace fTitle->fDeinterlace +#define fOutWidth fTitle->fOutWidth +#define fOutHeight fTitle->fOutHeight +#define fOutWidthMax fTitle->fOutWidthMax +#define fOutHeightMax fTitle->fOutHeightMax +#define fTopCrop fTitle->fTopCrop +#define fBottomCrop fTitle->fBottomCrop +#define fLeftCrop fTitle->fLeftCrop +#define fRightCrop fTitle->fRightCrop + +HBPictureView::HBPictureView( BRect rect, BBitmap * bitmap ) + : BView( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW ) +{ + fBitmap = bitmap; +} + +void HBPictureView::Draw( BRect rect ) +{ + if( LockLooper() ) + { + DrawBitmap( fBitmap, Bounds() ); + UnlockLooper(); + } + else + { + Log( "HBPictureView::Draw() : LockLooper() failed" ); + } + + BView::Draw( rect ); +} + + +/* Constructor */ +HBPictureWin::HBPictureWin( HBManager * manager, HBTitle * title ) + : BWindow( BRect( 0, 0, 0, 0 ), "Picture settings", + B_FLOATING_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, + B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_NOT_CLOSABLE ) +{ + fManager = manager; + fTitle = title; + + /* Resize & center */ + ResizeTo( fOutWidthMax + 40, fOutHeightMax + 280 ); + BScreen screen; + MoveTo( ( screen.Frame().Width() - Frame().Width() ) / 2, + ( screen.Frame().Height() - Frame().Height() ) / 2 ); + + /* Build the GUI */ + BRect r; + + /* Add a background view */ + BView * view; + view = new BView( Bounds(), NULL, B_FOLLOW_ALL, B_WILL_DRAW ); + view->SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); + AddChild( view ); + + /* First box : picture + slider */ + r = BRect( 10, 10, fOutWidthMax + 31, fOutHeightMax + 60 ); + BBox * pictureBox; + pictureBox = new BBox( r, NULL ); + pictureBox->SetLabel( "Preview" ); + + /* Leave a one-pixel margin to draw the white line around the picture */ + fBitmap = new BBitmap( BRect( 0, 0, fOutWidthMax + 1, + fOutHeightMax + 1 ), 0, B_RGB32 ); + + /* Picture view */ + r = BRect( 10, 15, fOutWidthMax + 11, fOutHeightMax + 16 ); + fPictureView = new HBPictureView( r, fBitmap ); + pictureBox->AddChild( fPictureView ); + + /* Slider */ + r = BRect( 10, fOutHeightMax + 25, fOutWidthMax + 11, + fOutHeightMax + 55 ); + fPictureSlider = new BSlider( r, NULL, NULL, + new BMessage( UPDATE_BITMAP ), 0, 9 ); + pictureBox->AddChild( fPictureSlider ); + + view->AddChild( pictureBox ); + + /* Second box : resize & crop settings */ + r = BRect( 10, fOutHeightMax + 75, fOutWidthMax + 31, + fOutHeightMax + 235 ); + BBox * settingsBox; + settingsBox = new BBox( r, NULL ); + settingsBox->SetLabel( "Settings" ); + + r = BRect( 10, 15, fOutWidthMax + 11, 30 ); + fDeinterlaceCheck = new BCheckBox( r, NULL, "Deinterlace", + new BMessage( UPDATE_BITMAP ) ); + fDeinterlaceCheck->SetValue( fDeinterlace ? 1 : 0 ); + settingsBox->AddChild( fDeinterlaceCheck ); + + r = BRect( 10, 40, fOutWidthMax + 11, 70 ); + fWidthSlider = new BSlider( r, NULL, "Picture size", + new BMessage( UPDATE_BITMAP ), + 1, fOutWidthMax / 16, + B_TRIANGLE_THUMB ); + fWidthSlider->SetValue( fOutWidth / 16 ); + settingsBox->AddChild( fWidthSlider ); + + r = BRect( 10, 80, ( fOutWidthMax / 2 ) + 5, 110 ); + fTopCropSlider = new BSlider( r, NULL, "Top cropping", + new BMessage( UPDATE_BITMAP ), + 0, fInHeight / 4, + B_TRIANGLE_THUMB ); + fTopCropSlider->SetValue( fTopCrop / 2 ); + settingsBox->AddChild( fTopCropSlider ); + + r = BRect( ( fOutWidthMax / 2 ) + 15, 80, fOutWidthMax + 11, 110 ); + fBottomCropSlider = new BSlider( r, NULL, "Bottom cropping", + new BMessage( UPDATE_BITMAP ), + 0, fInHeight / 4, + B_TRIANGLE_THUMB ); + fBottomCropSlider->SetValue( fBottomCrop / 2 ); + settingsBox->AddChild( fBottomCropSlider ); + + r = BRect( 10, 120, ( fOutWidthMax / 2 ) + 5, 150 ); + fLeftCropSlider = new BSlider( r, NULL, "Left cropping", + new BMessage( UPDATE_BITMAP ), + 0, fInWidth / 4, + B_TRIANGLE_THUMB ); + fLeftCropSlider->SetValue( fLeftCrop / 2 ); + settingsBox->AddChild( fLeftCropSlider ); + + r = BRect( ( fOutWidthMax / 2 ) + 15, 120, fOutWidthMax + 11, 150 ); + fRightCropSlider = new BSlider( r, NULL, "Right cropping", + new BMessage( UPDATE_BITMAP ), + 0, fInWidth / 4, + B_TRIANGLE_THUMB ); + fRightCropSlider->SetValue( fRightCrop / 2 ); + settingsBox->AddChild( fRightCropSlider ); + + view->AddChild( settingsBox ); + + /* "Close" button */ + r = BRect( fOutWidthMax - 49, fOutHeightMax + 245, + fOutWidthMax + 31, fOutHeightMax + 270 ); + BButton * button = new BButton( r, NULL, "OK", + new BMessage( B_QUIT_REQUESTED ) ); + view->AddChild( button ); + + UpdateBitmap( 0 ); +} + +void HBPictureWin::MessageReceived( BMessage * message ) +{ + switch( message->what ) + { + case UPDATE_BITMAP: + UpdateBitmap( fPictureSlider->Value() ); + fPictureView->Draw( fPictureView->Bounds() ); + break; + + default: + BWindow::MessageReceived( message ); + } +} + +void HBPictureWin::UpdateBitmap( int image ) +{ + fOutWidth = 16 * fWidthSlider->Value(); + fTopCrop = 2 * fTopCropSlider->Value(); + fBottomCrop = 2 * fBottomCropSlider->Value(); + fLeftCrop = 2 * fLeftCropSlider->Value(); + fRightCrop = 2 * fRightCropSlider->Value(); + fDeinterlace = ( fDeinterlaceCheck->Value() != 0 ); + + uint8_t * preview = fManager->GetPreview( fTitle, image ); + for( uint32_t i = 0; i < fOutHeightMax + 2; i++ ) + { + memcpy( ((uint8_t*) fBitmap->Bits()) + + i * fBitmap->BytesPerRow(), + preview + 4 * ( fOutWidthMax + 2 ) * i, + 4 * ( fOutWidthMax + 2 ) ); + } + free( preview ); + + if( !Lock() ) + { + Log( "HBPictureWin::UpdateBitmap() : cannot Lock()" ); + return; + } + + char label[128]; + + memset( label, 0, 128 ); + snprintf( label, 128, "Picture size : %d x %d", + fOutWidth, fOutHeight ); + fWidthSlider->SetValue( fOutWidth / 16 ); + fWidthSlider->SetLabel( label ); + + memset( label, 0, 128 ); + snprintf( label, 128, "Top cropping : %d", fTopCrop ); + fTopCropSlider->SetLabel( label ); + + memset( label, 0, 128 ); + snprintf( label, 128, "Bottom cropping : %d", fBottomCrop ); + fBottomCropSlider->SetLabel( label ); + + memset( label, 0, 128 ); + snprintf( label, 128, "Left cropping : %d", fLeftCrop ); + fLeftCropSlider->SetLabel( label ); + + memset( label, 0, 128 ); + snprintf( label, 128, "Right cropping : %d", fRightCrop ); + fRightCropSlider->SetLabel( label ); + + Unlock(); +} diff --git a/HBPictureWin.h b/beos/PictureWin.h index 9f1e37648..909e8ea51 100644 --- a/HBPictureWin.h +++ b/beos/PictureWin.h @@ -1,21 +1,26 @@ -/* $Id: HBPictureWin.h,v 1.6 2003/08/20 20:30:30 titer Exp $ */ +/* $Id: PictureWin.h,v 1.3 2003/09/30 14:38:15 titer Exp $ -#ifndef _HB_PICTURE_WIN_H -#define _HB_PICTURE_WIN_H + 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. */ -class HBTitleInfo; +#ifndef HB_PICTURE_WIN_H +#define HB_PICTURE_WIN_H #include <View.h> #include <Window.h> class BSlider; class BCheckBox; +/* libhb headers */ +#include "Common.h" + class HBPictureView : public BView { public: HBPictureView::HBPictureView( BRect rect, BBitmap * bitmap ); virtual void Draw( BRect rect ); - + private: BBitmap * fBitmap; }; @@ -23,15 +28,15 @@ class HBPictureView : public BView class HBPictureWin : public BWindow { public: - HBPictureWin( HBTitleInfo * titleInfo ); - virtual bool QuitRequested(); + HBPictureWin( HBManager * manager, HBTitle * title ); virtual void MessageReceived( BMessage * message ); - + void UpdateBitmap( int which ); - - + + private: - HBTitleInfo * fTitleInfo; + HBManager * fManager; + HBTitle * fTitle; /* GUI */ HBPictureView * fPictureView; @@ -43,10 +48,6 @@ class HBPictureWin : public BWindow BSlider * fLeftCropSlider; BSlider * fRightCropSlider; BCheckBox * fDeinterlaceCheck; - - /* Internal infos */ - uint32_t fMaxOutWidth; - uint32_t fMaxOutHeight; }; #endif diff --git a/HBAc3Decoder.cpp b/core/Ac3Decoder.cpp index b78097746..12eed05df 100644 --- a/HBAc3Decoder.cpp +++ b/core/Ac3Decoder.cpp @@ -1,23 +1,33 @@ -/* $Id: HBAc3Decoder.cpp,v 1.7 2003/08/25 19:47:14 titer Exp $ */ +/* $Id: Ac3Decoder.cpp,v 1.12 2003/09/30 14:38:15 titer Exp $ -#include "HBCommon.h" -#include "HBAc3Decoder.h" -#include "HBManager.h" -#include "HBFifo.h" + 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 "Ac3Decoder.h" +#include "Fifo.h" +#include "Manager.h" extern "C" { #include <a52dec/a52.h> } -HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudioInfo * audioInfo ) +HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudio * audio ) : HBThread( "ac3decoder" ) { fManager = manager; - fAudioInfo = audioInfo; - + fAudio = audio; + + /* Max size for a A52 frame is 3840 bytes */ + fAc3Frame = new HBBuffer( 3840 ); fAc3Buffer = NULL; - fAc3Frame = NULL; fPosInBuffer = 0; + fPosition = 0; +} + +HBAc3Decoder::~HBAc3Decoder() +{ + delete fAc3Frame; } void HBAc3Decoder::DoWork() @@ -26,55 +36,59 @@ void HBAc3Decoder::DoWork() a52_state_t * state = a52_init( 0 ); int inFlags = 0; int outFlags = A52_STEREO; - float sampleLevel = 32768; /* lame wants samples from - -32768 to 32768 */ - - /* Max size for a A52 frame is 3840 bytes */ - fAc3Frame = new HBBuffer( 3840 ); + + /* Lame wants samples from -32768 to 32768 */ + float sampleLevel = 32768; int frameSize; HBBuffer * rawBuffer; sample_t * samples; - + /* Main loop */ - while( !fDie ) + for( ;; ) { + while( fSuspend ) + { + Snooze( 10000 ); + } + fAc3Frame->fSize = 0; - + /* Get a frame header (7 bytes) */ if( !( GetBytes( 7 ) ) ) { - continue; + break; } - + /* Get the size of the current frame */ frameSize = a52_syncinfo( fAc3Frame->fData, &inFlags, - &fAudioInfo->fInSampleRate, - &fAudioInfo->fInBitrate ); - + &fAudio->fInSampleRate, + &fAudio->fInBitrate ); + if( !frameSize ) { Log( "HBAc3Decoder : a52_syncinfo failed" ); fManager->Error(); break; } - + /* Get the whole frame */ if( !( GetBytes( (uint32_t) frameSize ) ) ) { - continue; + break; } /* Feed liba52 */ a52_frame( state, fAc3Frame->fData, &outFlags, &sampleLevel, 0 ); - + /* 6 blocks per frame, 256 samples per block */ rawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) ); + rawBuffer->fPosition = fPosition; for( int i = 0; i < 6; i++ ) { /* Decode a block */ a52_block( state ); - + /* Get a pointer to the raw data */ samples = a52_samples( state ); @@ -82,18 +96,18 @@ void HBAc3Decoder::DoWork() memcpy( (float*) rawBuffer->fData + i * 256, samples, 256 * sizeof( float ) ); - + /* Copy right channel data */ memcpy( (float*) rawBuffer->fData + ( 6 + i ) * 256, samples + 256, 256 * sizeof( float ) ); } - - fAudioInfo->fRawFifo->Push( rawBuffer ); + + if( !Push( fAudio->fRawFifo, rawBuffer ) ) + { + break; + } } - - /* Clean up */ - delete fAc3Frame; } /* GetBytes() : pops buffers from the AC3 fifo until fAc3Frame @@ -104,13 +118,14 @@ bool HBAc3Decoder::GetBytes( uint32_t size ) { if( !fAc3Buffer ) { - if( !( fAc3Buffer = fAudioInfo->fAc3Fifo->Pop() ) ) + if( !( fAc3Buffer = Pop( fAudio->fAc3Fifo ) ) ) { return false; } fPosInBuffer = 0; + fPosition = fAc3Buffer->fPosition; } - + int willCopy = MIN( size - fAc3Frame->fSize, fAc3Buffer->fSize - fPosInBuffer ); memcpy( fAc3Frame->fData + fAc3Frame->fSize, @@ -118,13 +133,13 @@ bool HBAc3Decoder::GetBytes( uint32_t size ) willCopy ); fAc3Frame->fSize += willCopy; fPosInBuffer += willCopy; - + if( fAc3Buffer->fSize == fPosInBuffer ) { delete fAc3Buffer; fAc3Buffer = NULL; } } - + return true; } diff --git a/core/Ac3Decoder.h b/core/Ac3Decoder.h new file mode 100644 index 000000000..8226bb365 --- /dev/null +++ b/core/Ac3Decoder.h @@ -0,0 +1,33 @@ +/* $Id: Ac3Decoder.h,v 1.6 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. */ + +#ifndef HB_AC3_DECODER_H +#define HB_AC3_DECODER_H + +#include "Common.h" +#include "Thread.h" + +class HBAc3Decoder : public HBThread +{ + public: + HBAc3Decoder( HBManager * manager, + HBAudio * audio ); + ~HBAc3Decoder(); + + private: + void DoWork(); + bool GetBytes( uint32_t size ); + + HBManager * fManager; + HBAudio * fAudio; + + HBBuffer * fAc3Frame; + HBBuffer * fAc3Buffer; + uint32_t fPosInBuffer; + float fPosition; +}; + +#endif diff --git a/core/AviMuxer.cpp b/core/AviMuxer.cpp new file mode 100644 index 000000000..3b77b9c53 --- /dev/null +++ b/core/AviMuxer.cpp @@ -0,0 +1,479 @@ +/* $Id: AviMuxer.cpp,v 1.14 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 "AviMuxer.h" +#include "Manager.h" + +#define AVIF_HASINDEX 0x10 +#define AVIIF_KEYFRAME 0x10 + +#define FOURCC(a) ( ( a[3] << 24 ) | ( a[2] << 16 ) | ( a[1] << 8 ) | a[0] ) + +/* TODO : check return values from fputc/fwrite in case disk is full + or something */ + +void WriteInt8( FILE * file, uint8_t val ) +{ + fputc( val, file ); +} + +void WriteInt16( FILE * file, uint16_t val ) +{ + fputc( val & 0xFF, file ); + fputc( val >> 8, file ); +} + +void WriteInt32( FILE * file, uint32_t val ) +{ + fputc( val & 0xFF, file ); + fputc( ( val >> 8 ) & 0xFF, file ); + fputc( ( val >> 16 ) & 0xFF, file ); + fputc( val >> 24, file ); +} + +void WriteBuffer( FILE * file, HBBuffer * buffer ) +{ + fwrite( buffer->fData, buffer->fSize, 1, file ); +} + +void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo ) +{ + WriteInt32( file, bitmapInfo->FourCC ); + WriteInt32( file, bitmapInfo->BytesCount ); + WriteInt32( file, bitmapInfo->Size ); + WriteInt32( file, bitmapInfo->Width ); + WriteInt32( file, bitmapInfo->Height ); + WriteInt16( file, bitmapInfo->Planes ); + WriteInt16( file, bitmapInfo->BitCount ); + WriteInt32( file, bitmapInfo->Compression ); + WriteInt32( file, bitmapInfo->SizeImage ); + WriteInt32( file, bitmapInfo->XPelsPerMeter ); + WriteInt32( file, bitmapInfo->YPelsPerMeter ); + WriteInt32( file, bitmapInfo->ClrUsed ); + WriteInt32( file, bitmapInfo->ClrImportant ); + WriteInt8( file, bitmapInfo->Blue ); + WriteInt8( file, bitmapInfo->Green ); + WriteInt8( file, bitmapInfo->Red ); + WriteInt8( file, bitmapInfo->Reserved ); +} + +void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx ) +{ + WriteInt32( file, waveFormatEx->FourCC ); + WriteInt32( file, waveFormatEx->BytesCount ); + WriteInt16( file, waveFormatEx->FormatTag ); + WriteInt16( file, waveFormatEx->Channels ); + WriteInt32( file, waveFormatEx->SamplesPerSec ); + WriteInt32( file, waveFormatEx->AvgBytesPerSec ); + WriteInt16( file, waveFormatEx->BlockAlign ); + WriteInt16( file, waveFormatEx->BitsPerSample ); + WriteInt16( file, waveFormatEx->Size ); + WriteInt16( file, waveFormatEx->Id ); + WriteInt32( file, waveFormatEx->Flags ); + WriteInt16( file, waveFormatEx->BlockSize ); + WriteInt16( file, waveFormatEx->FramesPerBlock ); + WriteInt16( file, waveFormatEx->CodecDelay ); +} + +void WriteMainHeader( FILE * file, AviMainHeader * mainHeader ) +{ + WriteInt32( file, mainHeader->FourCC ); + WriteInt32( file, mainHeader->BytesCount ); + WriteInt32( file, mainHeader->MicroSecPerFrame ); + WriteInt32( file, mainHeader->MaxBytesPerSec ); + WriteInt32( file, mainHeader->PaddingGranularity ); + WriteInt32( file, mainHeader->Flags ); + WriteInt32( file, mainHeader->TotalFrames ); + WriteInt32( file, mainHeader->InitialFrames ); + WriteInt32( file, mainHeader->Streams ); + WriteInt32( file, mainHeader->SuggestedBufferSize ); + WriteInt32( file, mainHeader->Width ); + WriteInt32( file, mainHeader->Height ); + WriteInt32( file, mainHeader->Reserved[0] ); + WriteInt32( file, mainHeader->Reserved[1] ); + WriteInt32( file, mainHeader->Reserved[2] ); + WriteInt32( file, mainHeader->Reserved[3] ); +} + +void WriteStreamHeader( FILE * file, AviStreamHeader * streamHeader ) +{ + WriteInt32( file, streamHeader->FourCC ); + WriteInt32( file, streamHeader->BytesCount ); + WriteInt32( file, streamHeader->Type ); + WriteInt32( file, streamHeader->Handler ); + WriteInt32( file, streamHeader->Flags ); + WriteInt16( file, streamHeader->Priority ); + WriteInt16( file, streamHeader->Language ); + WriteInt32( file, streamHeader->InitialFrames ); + WriteInt32( file, streamHeader->Scale ); + WriteInt32( file, streamHeader->Rate ); + WriteInt32( file, streamHeader->Start ); + WriteInt32( file, streamHeader->Length ); + WriteInt32( file, streamHeader->SuggestedBufferSize ); + WriteInt32( file, streamHeader->Quality ); + WriteInt32( file, streamHeader->SampleSize ); + WriteInt16( file, streamHeader->Left ); + WriteInt16( file, streamHeader->Top ); + WriteInt16( file, streamHeader->Right ); + WriteInt16( file, streamHeader->Bottom ); +} + +HBAviIndex::HBAviIndex( uint32_t size ) + : HBBuffer( size ) +{ + fSize = 0; +} + +void HBAviIndex::WriteInt32( uint32_t val ) +{ + if( fSize + 16 > fAllocSize ) + { + /* Realloc if needed */ + Log( "HBAviIndex::WriteInt32() : reallocing index (%d -> %d MB)", + fAllocSize / ( 1024 * 1024 ), + 1 + fAllocSize / ( 1024 * 1024 ) ); + ReAlloc( fAllocSize + 1024 * 1024 ); + } + + fData[fSize] = val & 0xFF; + fData[fSize + 1] = ( val >> 8 ) & 0xFF; + fData[fSize + 2] = ( val >> 16 ) & 0xFF; + fData[fSize + 3] = val >> 24; + + fSize += 4; +} + +HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title, + HBAudio * audio1, HBAudio * audio2, + char * fileName ) + : HBThread( "avimuxer" ) +{ + fManager = manager; + fTitle = title; + fAudio1 = audio1; + fAudio2 = audio2; + fFileName = strdup( fileName ); + + fVideoBuffer = NULL; + fAudio1Buffer = NULL; + fAudio2Buffer = NULL; + + fRiffBytesCount = 2040; + fMoviBytesCount = 4; +} + +void HBAviMuxer::DoWork() +{ + /* Open the destination file */ + if( !( fFile = fopen( fFileName, "w" ) ) ) + { + Log( "HBAviMuxer: fopen failed" ); + fManager->Error(); + return; + } + + /* Initializations */ + memset( &fMainHeader, 0, sizeof( AviMainHeader ) ); + memset( &fVideoStreamHeader, 0, sizeof( AviStreamHeader ) ); + memset( &fAudio1StreamHeader, 0, sizeof( AviStreamHeader ) ); + memset( &fAudio2StreamHeader, 0, sizeof( AviStreamHeader ) ); + memset( &fVideoStreamFormat, 0, sizeof( BitmapInfo ) ); + memset( &fAudio1StreamFormat, 0, sizeof( WaveFormatEx ) ); + memset( &fAudio2StreamFormat, 0, sizeof( WaveFormatEx ) ); + + /* Alloc an 1 MB index (to be realloced later if needed) */ + fIndex = new HBAviIndex( 1024 * 1024 ); + + /* Main loop */ + for( ;; ) + { + while( fSuspend ) + { + Snooze( 10000 ); + } + + if( !fVideoBuffer ) + { + fVideoBuffer = Pop( fTitle->fMpeg4Fifo ); + } + if( fAudio1 && !fAudio1Buffer ) + { + fAudio1Buffer = Pop( fAudio1->fMp3Fifo ); + } + if( fAudio2 && !fAudio2Buffer ) + { + fAudio2Buffer = Pop( fAudio2->fMp3Fifo ); + } + + if( !fVideoBuffer && !fAudio1Buffer && !fAudio2Buffer ) + { + break; + } + + if( fVideoBuffer && + ( !fAudio1Buffer || + fVideoBuffer->fPosition < fAudio1Buffer->fPosition ) && + ( !fAudio2Buffer || + fVideoBuffer->fPosition < fAudio2Buffer->fPosition ) ) + { + AddVideoChunk(); + } + else if( fAudio1Buffer && + ( !fAudio2Buffer || + fAudio1Buffer->fPosition < fAudio2Buffer->fPosition ) ) + { + AddAudioChunk( 1 ); + } + else + { + AddAudioChunk( 2 ); + } + } + + /* Write the index */ + fseek( fFile, 0, SEEK_END ); + WriteInt32( fFile, FOURCC( "idx1" ) ); + WriteInt32( fFile, fIndex->fSize ); + WriteBuffer( fFile, fIndex ); + + /* Update the headers */ + fRiffBytesCount += 8 + fIndex->fSize; + fMainHeader.Flags |= AVIF_HASINDEX; + UpdateMainHeader(); + + delete fIndex; + + fclose( fFile ); +} + +bool HBAviMuxer::AddVideoChunk() +{ + fRiffBytesCount += 8 + EVEN( fVideoBuffer->fSize ); + fMoviBytesCount += 8 + EVEN( fVideoBuffer->fSize ); + + fMainHeader.MicroSecPerFrame = 1000000 * (uint64_t) fTitle->fScale / + fTitle->fRate; + fMainHeader.TotalFrames++; + fMainHeader.Width = fTitle->fOutWidth; + fMainHeader.Height = fTitle->fOutHeight; + + fVideoStreamHeader.FourCC = FOURCC( "strh" ); + fVideoStreamHeader.BytesCount = AVI_STREAM_HEADER_SIZE - 8; + fVideoStreamHeader.Type = FOURCC( "vids" ); + fVideoStreamHeader.Handler = FOURCC( "DIVX" ); + fVideoStreamHeader.Scale = fTitle->fScale; + fVideoStreamHeader.Rate = fTitle->fRate; + fVideoStreamHeader.Length++; + + fVideoStreamFormat.FourCC = FOURCC( "strf" ); + fVideoStreamFormat.BytesCount = BITMAP_INFO_SIZE - 8; + fVideoStreamFormat.Size = BITMAP_INFO_SIZE - 8; + fVideoStreamFormat.Width = fTitle->fOutWidth; + fVideoStreamFormat.Height = fTitle->fOutHeight; + fVideoStreamFormat.Planes = 1; + fVideoStreamFormat.BitCount = 24; + fVideoStreamFormat.Compression = FOURCC( "DIVX" );; + + UpdateMainHeader(); + + fseek( fFile, 0, SEEK_END ); + + /* Update the index */ + fIndex->WriteInt32( FOURCC( "00dc" ) ); + fIndex->WriteInt32( fVideoBuffer->fKeyFrame ? AVIIF_KEYFRAME : 0 ); + fIndex->WriteInt32( ftell( fFile ) - 2044 ); + fIndex->WriteInt32( fVideoBuffer->fSize ); + + /* Write the chunk */ + WriteInt32( fFile, FOURCC( "00dc" ) ); + WriteInt32( fFile, fVideoBuffer->fSize ); + WriteBuffer( fFile, fVideoBuffer ); + + /* Chunks must be 2-bytes aligned */ + if( fVideoBuffer->fSize & 1 ) + { + WriteInt8( fFile, 0 ); + } + + delete fVideoBuffer; + fVideoBuffer = NULL; + + return true; +} + +bool HBAviMuxer::AddAudioChunk( int track ) +{ + HBAudio * info; + HBBuffer * buffer; + AviStreamHeader * streamHeader; + WaveFormatEx * streamFormat; + + if( track == 1 ) + { + info = fAudio1; + buffer = fAudio1Buffer; + streamHeader = &fAudio1StreamHeader; + streamFormat = &fAudio1StreamFormat; + } + else + { + info = fAudio2; + buffer = fAudio2Buffer; + streamHeader = &fAudio2StreamHeader; + streamFormat = &fAudio2StreamFormat; + } + + fRiffBytesCount += 8 + EVEN( buffer->fSize ); + fMoviBytesCount += 8 + EVEN( buffer->fSize ); + + streamHeader->FourCC = FOURCC( "strh" ); + streamHeader->BytesCount = AVI_STREAM_HEADER_SIZE - 8; + streamHeader->Type = FOURCC( "auds" ); + streamHeader->InitialFrames = 1; + streamHeader->Scale = 1152; + streamHeader->Rate = info->fOutSampleRate; + streamHeader->Length++; + streamHeader->Quality = 0xFFFFFFFF; + + + streamFormat->FourCC = FOURCC( "strf" ); + streamFormat->BytesCount = WAVE_FORMAT_EX_SIZE - 8; + streamFormat->FormatTag = 0x55; + streamFormat->Channels = 2; + streamFormat->SamplesPerSec = info->fOutSampleRate; + streamFormat->AvgBytesPerSec = info->fOutBitrate * 1024 / 8; + streamFormat->BlockAlign = 1152; + + /* stolen from libavformat/wav.c */ + streamFormat->Size = 12; + streamFormat->Id = 1; + streamFormat->Flags = 2; + streamFormat->BlockSize = 1152; + streamFormat->FramesPerBlock = 1; + streamFormat->CodecDelay = 1393; + + UpdateMainHeader(); + + fseek( fFile, 0, SEEK_END ); + + /* Update the index */ + if( track == 1 ) + { + fIndex->WriteInt32( FOURCC( "01wb" ) ); + } + else + { + fIndex->WriteInt32( FOURCC( "02wb" ) ); + } + fIndex->WriteInt32( buffer->fKeyFrame ? AVIIF_KEYFRAME : 0 ); + fIndex->WriteInt32( ftell( fFile ) - 2044 ); + fIndex->WriteInt32( buffer->fSize ); + + /* Write the chunk */ + WriteInt32( fFile, + ( track == 1 ) ? FOURCC( "01wb" ) : FOURCC( "02wb" ) ); + WriteInt32( fFile, buffer->fSize ); + WriteBuffer( fFile, buffer ); + + /* Chunks must be 2-bytes aligned */ + if( buffer->fSize & 1 ) + { + WriteInt8( fFile, 0 ); + } + + delete buffer; + if( track == 1 ) + { + fAudio1Buffer = NULL; + } + else + { + fAudio2Buffer = NULL; + } + + return true; +} + +void HBAviMuxer::UpdateMainHeader() +{ + fMainHeader.FourCC = FOURCC( "avih" ); + fMainHeader.BytesCount = AVI_MAIN_HEADER_SIZE - 8; + fMainHeader.Streams = 1 + ( fAudio1 ? 1 : 0 ) + + ( fAudio2 ? 1 : 0 ); + + fHdrlBytesCount = 4 + AVI_MAIN_HEADER_SIZE + 12 + + AVI_STREAM_HEADER_SIZE + BITMAP_INFO_SIZE; + + if( fAudio1 ) + { + fHdrlBytesCount += 12 + AVI_STREAM_HEADER_SIZE + + WAVE_FORMAT_EX_SIZE; + } + if( fAudio2 ) + { + fHdrlBytesCount += 12 + AVI_STREAM_HEADER_SIZE + + WAVE_FORMAT_EX_SIZE; + } + + fseek( fFile, 0, SEEK_SET ); + WriteInt32( fFile, FOURCC( "RIFF" ) ); + WriteInt32( fFile, fRiffBytesCount ); + WriteInt32( fFile, FOURCC( "AVI " ) ); + WriteInt32( fFile, FOURCC( "LIST" ) ); + WriteInt32( fFile, fHdrlBytesCount ); + WriteInt32( fFile, FOURCC( "hdrl" ) ); + + WriteMainHeader( fFile, &fMainHeader ); + + int strlSize; + strlSize = 4 + AVI_STREAM_HEADER_SIZE + BITMAP_INFO_SIZE; + WriteInt32( fFile, FOURCC( "LIST" ) ); + WriteInt32( fFile, strlSize ); + WriteInt32( fFile, FOURCC( "strl" ) ); + + WriteStreamHeader( fFile, &fVideoStreamHeader ); + WriteBitmapInfo( fFile, &fVideoStreamFormat ); + + if( fAudio1 ) + { + strlSize = 4 + AVI_STREAM_HEADER_SIZE + WAVE_FORMAT_EX_SIZE; + WriteInt32( fFile, FOURCC( "LIST" ) ); + WriteInt32( fFile, strlSize ); + WriteInt32( fFile, FOURCC( "strl" ) ); + WriteStreamHeader( fFile, &fAudio1StreamHeader ); + WriteWaveFormatEx( fFile, &fAudio1StreamFormat ); + } + + if( fAudio2 ) + { + strlSize = 4 + AVI_STREAM_HEADER_SIZE + WAVE_FORMAT_EX_SIZE; + WriteInt32( fFile, FOURCC( "LIST" ) ); + WriteInt32( fFile, strlSize ); + WriteInt32( fFile, FOURCC( "strl" ) ); + WriteStreamHeader( fFile, &fAudio2StreamHeader ); + WriteWaveFormatEx( fFile, &fAudio2StreamFormat ); + } + + /* a JUNK chunk to fill the free space. + size = 2048 -/ + 12 ("RIFFxxxxAVI ") - + 8 (hdrl's "LIS1Txxxx") - + fHdrlBytesCount - + 8 ("JUNKxxxx") - + 12 ("LISTxxxxmovi) */ + int junkSize = 2008 - fHdrlBytesCount; + WriteInt32( fFile, FOURCC( "JUNK" ) ); + WriteInt32( fFile, junkSize ); + for( uint32_t i = 0; i < 2008 - fHdrlBytesCount; i++ ) + { + WriteInt8( fFile, 0 ); + } + + /* movi list */ + WriteInt32( fFile, FOURCC( "LIST" ) ); + WriteInt32( fFile, fMoviBytesCount ); + WriteInt32( fFile, FOURCC( "movi" ) ); +} diff --git a/core/AviMuxer.h b/core/AviMuxer.h new file mode 100644 index 000000000..842f7a87a --- /dev/null +++ b/core/AviMuxer.h @@ -0,0 +1,153 @@ +/* $Id: AviMuxer.h,v 1.10 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. */ + +#ifndef HB_AVI_MUXER_H +#define HB_AVI_MUXER_H + +#include "Common.h" +#include "Fifo.h" +#include "Thread.h" + +/* Misc structures used in AVI headers */ +#define BITMAP_INFO_SIZE 52 +typedef struct BitmapInfo +{ + uint32_t FourCC; + uint32_t BytesCount; + uint32_t Size; + uint32_t Width; + uint32_t Height; + uint16_t Planes; + uint16_t BitCount; + uint32_t Compression; + uint32_t SizeImage; + uint32_t XPelsPerMeter; + uint32_t YPelsPerMeter; + uint32_t ClrUsed; + uint32_t ClrImportant; + uint8_t Blue; + uint8_t Green; + uint8_t Red; + uint8_t Reserved; +} BitmapInfo; + +#define WAVE_FORMAT_EX_SIZE 38 +typedef struct WaveFormatEx +{ + uint32_t FourCC; + uint32_t BytesCount; + uint16_t FormatTag; + uint16_t Channels; + uint32_t SamplesPerSec; + uint32_t AvgBytesPerSec; + uint16_t BlockAlign; + uint16_t BitsPerSample; + uint16_t Size; + + /* mp3 specific */ + uint16_t Id; + uint32_t Flags; + uint16_t BlockSize; + uint16_t FramesPerBlock; + uint16_t CodecDelay; +} WaveFormatEx; + +#define AVI_STREAM_HEADER_SIZE 64 +typedef struct AviStreamHeader +{ + uint32_t FourCC; + uint32_t BytesCount; + uint32_t Type; + uint32_t Handler; + uint32_t Flags; + uint16_t Priority; + uint16_t Language; + uint32_t InitialFrames; + uint32_t Scale; + uint32_t Rate; + uint32_t Start; + uint32_t Length; + uint32_t SuggestedBufferSize; + uint32_t Quality; + uint32_t SampleSize; + int16_t Left; + int16_t Top; + int16_t Right; + int16_t Bottom; +} AviStreamHeader; + +#define AVI_MAIN_HEADER_SIZE 64 +typedef struct AviMainHeader +{ + uint32_t FourCC; + uint32_t BytesCount; + uint32_t MicroSecPerFrame; + uint32_t MaxBytesPerSec; + uint32_t PaddingGranularity; + uint32_t Flags; + uint32_t TotalFrames; + uint32_t InitialFrames; + uint32_t Streams; + uint32_t SuggestedBufferSize; + uint32_t Width; + uint32_t Height; + uint32_t Reserved[4]; +} AviMainHeader; + +class HBAviIndex : public HBBuffer +{ + public: + HBAviIndex( uint32_t size ); + void WriteInt32( uint32_t val ); +}; + +class HBAviMuxer : public HBThread +{ + public: + HBAviMuxer( HBManager * manager, + HBTitle * title, HBAudio * audio1, + HBAudio * audio2, + char * fileName ); + + private: + void DoWork(); + bool AddVideoChunk(); + bool AddAudioChunk( int track ); + void UpdateMainHeader(); + + HBManager * fManager; + HBTitle * fTitle; + HBAudio * fAudio1; + HBAudio * fAudio2; + char * fFileName; + + FILE * fFile; + HBBuffer * fVideoBuffer; + HBBuffer * fAudio1Buffer; + HBBuffer * fAudio2Buffer; + + /* The main header */ + AviMainHeader fMainHeader; + + /* The video track */ + AviStreamHeader fVideoStreamHeader; + BitmapInfo fVideoStreamFormat; + + /* The audio tracks */ + AviStreamHeader fAudio1StreamHeader; + WaveFormatEx fAudio1StreamFormat; + AviStreamHeader fAudio2StreamHeader; + WaveFormatEx fAudio2StreamFormat; + + uint32_t fRiffBytesCount; + uint32_t fHdrlBytesCount; + uint32_t fMoviBytesCount; + + HBAviIndex * fIndex; + +}; + +#endif diff --git a/core/Common.cpp b/core/Common.cpp new file mode 100644 index 000000000..b9bb3e062 --- /dev/null +++ b/core/Common.cpp @@ -0,0 +1,220 @@ +/* $Id: Common.cpp,v 1.29 2003/09/30 21:21:32 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. */ + +#if defined( SYS_BEOS ) +# include <OS.h> +#endif + +#include "Common.h" +#include "Fifo.h" +#include "MpegDemux.h" +#include "Languages.h" + +#include <stdarg.h> +#include <time.h> +#include <sys/time.h> +#include <dvdread/ifo_types.h> +#include <dvdplay/dvdplay.h> +#include <dvdplay/info.h> +#include <dvdplay/state.h> +#include <dvdplay/nav.h> + +extern "C" { +#include <mpeg2dec/mpeg2.h> +} + +void Snooze( uint64_t time ) +{ +#if defined( SYS_BEOS ) + snooze( time ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + usleep( time ); +#endif +} + +void Log( char * log, ... ) +{ + if( !getenv( "HB_DEBUG" ) ) + { + return; + } + + char string[1024]; + + /* Show the time */ + time_t _now = time( NULL ); + struct tm * now = localtime( &_now ); + sprintf( string, "[%02d:%02d:%02d] ", + now->tm_hour, now->tm_min, now->tm_sec ); + + /* Convert the message to a string */ + va_list args; + va_start( args, log ); + int ret = vsnprintf( string + 11, 1011, log, args ); + va_end( args ); + + /* Add the end of line */ + string[ret+11] = '\n'; + string[ret+12] = '\0'; + + /* Print it */ + fprintf( stderr, "%s", string ); +} + +char * LanguageForCode( int code ) +{ + char codeString[2]; + codeString[0] = ( code >> 8 ) & 0xFF; + codeString[1] = code & 0xFF; + + iso639_lang_t * lang; + for( lang = languages; lang->engName; lang++ ) + { + if( !strncmp( lang->iso639_1, codeString, 2 ) ) + { + if( *lang->nativeName ) + return lang->nativeName; + + return lang->engName; + } + } + + return "Unknown"; +} + +uint64_t GetDate() +{ + struct timeval tv; + gettimeofday( &tv, NULL ); + return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec ); +} + +#define HBLIST_DEFAULT_SIZE 20 + +HBList::HBList() +{ + fItems = (void**) malloc( HBLIST_DEFAULT_SIZE * sizeof( void* ) ); + fAllocItems = HBLIST_DEFAULT_SIZE; + fNbItems = 0; +} + +HBList::~HBList() +{ + free( fItems ); +} + +uint32_t HBList::CountItems() +{ + return fNbItems; +} + +void HBList::AddItem( void * item ) +{ + if( !item ) + { + return; + } + + if( fNbItems == fAllocItems ) + { + fAllocItems += HBLIST_DEFAULT_SIZE; + fItems = (void**) realloc( fItems, fAllocItems * sizeof( void* ) ); + } + + fItems[fNbItems] = item; + + fNbItems++; +} + +void HBList::RemoveItem( void * item ) +{ + if( !item || !fNbItems ) + { + return; + } + + uint32_t i; + for( i = 0; i < fNbItems; i++ ) + { + if( fItems[i] == item ) + { + break; + } + } + + if( fItems[i] != item ) + { + Log( "HBList::RemoveItem() : item not in the list" ); + return; + } + + for( ; i < fNbItems - 1; i++ ) + { + fItems[i] = fItems[i+1]; + } + + fNbItems--; +} + +void * HBList::ItemAt( uint32_t index ) +{ + if( index < fNbItems ) + { + return fItems[index]; + } + + return NULL; +} + +HBTitle::HBTitle( char * device, int index ) +{ + fDevice = strdup( device ); + fIndex = index; + + fAudioList = new HBList(); + fPSFifo = NULL; + fMpeg2Fifo = NULL; + fRawFifo = NULL; + fMpeg4Fifo = NULL; + + fTopCrop = 0; + fBottomCrop = 0; + fLeftCrop = 0; + fRightCrop = 0; + fBitrate = 1024; + fDeinterlace = false; + fTwoPass = false; +} + +HBTitle::~HBTitle() +{ + HBAudio * audio; + + while( ( audio = (HBAudio*) fAudioList->ItemAt( 0 ) ) ) + { + fAudioList->RemoveItem( audio ); + delete audio; + } + delete fAudioList; +} + +/* Audio track */ +HBAudio::HBAudio( int id, char * description ) +{ + fId = id; + fDescription = strdup( description ); + fOutSampleRate = 44100; + fOutBitrate = 128; + + fAc3Fifo = NULL; + fRawFifo = NULL; + fMp3Fifo = NULL; +} + +HBAudio::~HBAudio() +{ + free( fDescription ); +} diff --git a/core/Common.h b/core/Common.h new file mode 100644 index 000000000..f4d40c8bd --- /dev/null +++ b/core/Common.h @@ -0,0 +1,192 @@ +/* $Id: Common.h,v 1.28 2003/10/03 16:18:08 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. */ + +#ifndef HB_COMMON_H +#define HB_COMMON_H + +/* Standard headers */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <inttypes.h> +typedef uint8_t byte_t; + +/* Misc structures */ +typedef struct dvdplay_s * dvdplay_ptr; +typedef struct mpeg2dec_s mpeg2dec_t; +typedef struct AVPicture AVPicture; +typedef struct AVFrame AVFrame; +typedef struct AVCodecContext AVCodecContext; +typedef struct ImgReSampleContext ImgReSampleContext; + +/* Classes */ +class HBAc3Decoder; +class HBAudio; +class HBAviIndex; +class HBAviMuxer; +class HBBuffer; +class HBDVDReader; +class HBFifo; +class HBList; +class HBLock; +class HBManager; +class HBMp3Encoder; +class HBMpeg2Decoder; +class HBMpeg4Encoder; +class HBMpegDemux; +class HBResizer; +class HBScanner; +class HBStatus; +class HBThread; +class HBTitle; + +/* Handy macros */ +#ifndef MIN +# define MIN( a, b ) ( ( (a) > (b) ) ? (b) : (a) ) +#endif +#ifndef MAX +# define MAX( a, b ) ( ( (a) > (b) ) ? (a) : (b) ) +#endif +#define EVEN( a ) ( ( (a) & 0x1 ) ? ( (a) + 1 ) : (a) ) +#define MULTIPLE_16( a ) ( 16 * ( ( (a) + 8 ) / 16 ) ) + +#define VOUT_ASPECT_FACTOR 432000 + +/* Global prototypes */ +void Snooze( uint64_t time ); +void Log( char * log, ... ); +char * LanguageForCode( int code ); +uint64_t GetDate(); + +/* Possible states */ +typedef enum +{ + HB_MODE_UNDEF = 0000, + HB_MODE_NEED_VOLUME = 0001, + HB_MODE_SCANNING = 0002, + HB_MODE_INVALID_VOLUME = 0004, + HB_MODE_READY_TO_RIP = 0010, + HB_MODE_ENCODING = 0020, + HB_MODE_SUSPENDED = 0040, + HB_MODE_DONE = 0100, + HB_MODE_CANCELED = 0200, + HB_MODE_ERROR = 0400 +} HBMode; + +class HBStatus +{ + public: + HBMode fMode; + + /* HB_MODE_SCANNING */ + char * fScannedVolume; + int fScannedTitle; + + /* HB_MODE_SCANDONE */ + HBList * fTitleList; + + /* HB_MODE_ENCODING || HB_MODE_SUSPENDED */ + float fPosition; + float fFrameRate; + uint32_t fFrames; + uint64_t fStartDate; + uint32_t fRemainingTime; /* in seconds */ + uint64_t fSuspendDate; +}; + +class HBList +{ + public: + HBList(); + ~HBList(); + uint32_t CountItems(); + void AddItem( void * item ); + void RemoveItem( void * item ); + void * ItemAt( uint32_t index ); + + private: + void ** fItems; + uint32_t fAllocItems; + uint32_t fNbItems; +}; + +class HBAudio +{ + public: + HBAudio( int id, char * description ); + ~HBAudio(); + + /* Ident */ + uint32_t fId; + char * fDescription; + + /* Settings */ + int fInSampleRate; + int fOutSampleRate; + int fInBitrate; + int fOutBitrate; + + /* Fifos */ + HBFifo * fAc3Fifo; + HBFifo * fRawFifo; + HBFifo * fMp3Fifo; + + /* Threads */ + HBAc3Decoder * fAc3Decoder; + HBMp3Encoder * fMp3Encoder; +}; + +class HBTitle +{ + public: + HBTitle( char * device, int index ); + ~HBTitle(); + + char * fDevice; + int fIndex; + uint64_t fLength; + + /* Video input */ + uint32_t fInWidth; + uint32_t fInHeight; + uint32_t fAspect; + uint32_t fRate; + uint32_t fScale; + + /* Video output */ + bool fDeinterlace; + uint32_t fOutWidth; + uint32_t fOutHeight; + uint32_t fOutWidthMax; + uint32_t fOutHeightMax; + uint32_t fTopCrop; + uint32_t fBottomCrop; + uint32_t fLeftCrop; + uint32_t fRightCrop; + uint32_t fBitrate; + bool fTwoPass; + + /* Audio infos */ + HBList * fAudioList; + + /* Fifos */ + HBFifo * fPSFifo; + HBFifo * fMpeg2Fifo; + HBFifo * fRawFifo; + HBFifo * fResizedFifo; + HBFifo * fMpeg4Fifo; + + /* Threads */ + HBDVDReader * fDVDReader; + HBMpegDemux * fMpegDemux; + HBMpeg2Decoder * fMpeg2Decoder; + HBResizer * fResizer; + HBMpeg4Encoder * fMpeg4Encoder; + HBAviMuxer * fAviMuxer; +}; + +#endif diff --git a/core/DVDReader.cpp b/core/DVDReader.cpp new file mode 100644 index 000000000..27c20d08a --- /dev/null +++ b/core/DVDReader.cpp @@ -0,0 +1,96 @@ +/* $Id: DVDReader.cpp,v 1.12 2003/10/03 16:49:19 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 "DVDReader.h" +#include "Manager.h" +#include "Fifo.h" + +#include <dvdread/ifo_types.h> +#include <dvdplay/dvdplay.h> +#include <dvdplay/info.h> +#include <dvdplay/state.h> +#include <dvdplay/nav.h> + +HBDVDReader::HBDVDReader( HBManager * manager, HBTitle * title ) + : HBThread( "dvdreader" ) +{ + fManager = manager; + fTitle = title; +} + +void HBDVDReader::DoWork() +{ + /* Open the device */ + dvdplay_ptr vmg; + vmg = dvdplay_open( fTitle->fDevice, NULL, NULL ); + if( !vmg ) + { + Log( "HBDVDReader: dvdplay_open() failed" ); + fManager->Error(); + return; + } + + bool die = false; + for( int i = 0; i < ( fTitle->fTwoPass ? 2 : 1 ); i++ ) + { + /* Open the title */ + dvdplay_start( vmg, fTitle->fIndex ); + + /* Read */ + HBBuffer * dvdBuffer; + int beginPosition = dvdplay_position( vmg ); + int endPosition = dvdplay_title_end( vmg ); + + while( dvdplay_position( vmg ) < endPosition ) + { + while( fSuspend ) + { + Snooze( 10000 ); + } + + dvdBuffer = new HBBuffer( DVD_VIDEO_LB_LEN ); + dvdBuffer->fPosition = (float) ( dvdplay_position( vmg ) + - beginPosition ) / + (float) ( endPosition - beginPosition ) ; + if( fTitle->fTwoPass ) + { + dvdBuffer->fPosition /= 2; + if( i == 1 ) + { + dvdBuffer->fPosition += 0.5; + } + } + dvdBuffer->fPass = fTitle->fTwoPass ? ( i + 1 ) : 0; + + if( dvdplay_read( vmg, dvdBuffer->fData, 1 ) < 0 ) + { + Log( "HBDVDReader: could not dvdplay_read()" ); + delete dvdBuffer; + fManager->Error(); + break; + } + + if( !Push( fTitle->fPSFifo, dvdBuffer ) ) + { + die = true; + break; + } + } + + if( die ) + { + break; + } + } + + if( !die ) + { + fManager->Done(); + } + + /* Clean up */ + dvdplay_close( vmg ); +} diff --git a/core/DVDReader.h b/core/DVDReader.h new file mode 100644 index 000000000..b76f57566 --- /dev/null +++ b/core/DVDReader.h @@ -0,0 +1,25 @@ +/* $Id: DVDReader.h,v 1.5 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. */ + +#ifndef HB_DVD_READER_H +#define HB_DVD_READER_H + +#include "Common.h" +#include "Thread.h" + +class HBDVDReader : public HBThread +{ + public: + HBDVDReader( HBManager * manager, HBTitle * title ); + + private: + void DoWork(); + + HBManager * fManager; + HBTitle * fTitle; +}; + +#endif diff --git a/core/Fifo.cpp b/core/Fifo.cpp new file mode 100644 index 000000000..35bcb0449 --- /dev/null +++ b/core/Fifo.cpp @@ -0,0 +1,119 @@ +/* $Id: Fifo.cpp,v 1.14 2003/10/02 15:44:52 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 "Fifo.h" +#include "Thread.h" + +HBBuffer::HBBuffer( uint32_t size ) +{ + fAllocSize = size; + fSize = size; + fKeyFrame = false; + fData = (uint8_t*) malloc( size ); + fPosition = 0; + + if( !fData ) + { + Log( "HBBuffer::HBBuffer() : malloc() failed, gonna crash soon" ); + } +} + +HBBuffer::~HBBuffer() +{ + free( fData ); +} + +void HBBuffer::ReAlloc( uint32_t size ) +{ + fData = (uint8_t*) realloc( fData, size ); + + if( !fData ) + { + Log( "HBBuffer::ReAlloc() : realloc() failed, gonna crash soon" ); + } + + fAllocSize = size; +} + +/* Constructor */ +HBFifo::HBFifo( int capacity ) +{ + fCapacity = capacity; + + fWhereToPush = 0; + fWhereToPop = 0; + fBuffers = (HBBuffer**) malloc( ( fCapacity + 1 ) * sizeof( void* ) ); + fLock = new HBLock(); +} + +HBFifo::~HBFifo() +{ + Log( "HBFifo::~HBFifo : trashing %d buffers", Size() ); + + /* Empty the fifo */ + while( fWhereToPush != fWhereToPop ) + { + HBBuffer * buffer = fBuffers[fWhereToPop]; + fWhereToPop++; + fWhereToPop %= ( fCapacity + 1 ); + delete buffer; + } + + /* Cleaning */ + free( fBuffers ); + + delete fLock; +} + +/* Size() : returns how much the fifo is currently filled */ +int HBFifo::Size() +{ + return ( fCapacity + 1 + fWhereToPush - fWhereToPop ) % + ( fCapacity + 1 ); +} + +/* Capacity() : simply returns the fifo capacity... */ +int HBFifo::Capacity() +{ + return fCapacity; +} + +/* Push() - returns immediatly (true if successful, false otherwise ) */ +bool HBFifo::Push( HBBuffer * buffer ) +{ + fLock->Lock(); + + if( Size() < fCapacity ) + { + fBuffers[fWhereToPush] = buffer; + fWhereToPush++; + fWhereToPush %= ( fCapacity + 1 ); + fLock->Unlock(); + return true; + } + + fLock->Unlock(); + return false; +} + +/* Pop() - returns immediatly (a pointer to a buffer if successful, + NULL otherwise ) */ +HBBuffer * HBFifo::Pop() +{ + fLock->Lock(); + + if( fWhereToPush != fWhereToPop ) + { + HBBuffer * buffer = fBuffers[fWhereToPop]; + fWhereToPop++; + fWhereToPop %= ( fCapacity + 1 ); + fLock->Unlock(); + return buffer; + } + + fLock->Unlock(); + return NULL; +} diff --git a/core/Fifo.h b/core/Fifo.h new file mode 100644 index 000000000..69200d30c --- /dev/null +++ b/core/Fifo.h @@ -0,0 +1,49 @@ +/* $Id: Fifo.h,v 1.11 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. */ + +#ifndef HB_FIFO_H +#define HB_FIFO_H + +#include "Common.h" + +class HBBuffer +{ + public: + HBBuffer( uint32_t size ); + ~HBBuffer(); + void ReAlloc( uint32_t size ); + + uint32_t fAllocSize; + uint32_t fSize; + uint8_t * fData; + + float fPosition; + uint32_t fStreamId; + bool fKeyFrame; + uint64_t fPTS; + uint32_t fPass; +}; + +class HBFifo +{ + public: + HBFifo( int capacity = 32 ); + ~HBFifo(); + + int Size(); + int Capacity(); + bool Push( HBBuffer * buffer ); + HBBuffer * Pop(); + + private: + int fCapacity; + int fWhereToPush; + int fWhereToPop; + HBBuffer ** fBuffers; + HBLock * fLock; +}; + +#endif diff --git a/core/Languages.h b/core/Languages.h new file mode 100644 index 000000000..21a5e1487 --- /dev/null +++ b/core/Languages.h @@ -0,0 +1,184 @@ +/* $Id: Languages.h,v 1.2 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. */ + +#ifndef HB_LANGUAGES_H +#define HB_LANGUAGES_H + +typedef struct iso639_lang_t +{ + char * engName; /* Description in English */ + char * nativeName; /* Description in native language */ + char * iso639_1; /* ISO-639-1 (2 characters) code */ +} iso639_lang_t; + +iso639_lang_t languages[] = +{ { "Afar", "", "aa" }, + { "Abkhazian", "", "ab" }, + { "Afrikaans", "", "af" }, + { "Albanian", "", "sq" }, + { "Amharic", "", "am" }, + { "Arabic", "", "ar" }, + { "Armenian", "", "hy" }, + { "Assamese", "", "as" }, + { "Avestan", "", "ae" }, + { "Aymara", "", "ay" }, + { "Azerbaijani", "", "az" }, + { "Bashkir", "", "ba" }, + { "Basque", "", "eu" }, + { "Belarusian", "", "be" }, + { "Bengali", "", "bn" }, + { "Bihari", "", "bh" }, + { "Bislama", "", "bi" }, + { "Bosnian", "", "bs" }, + { "Breton", "", "br" }, + { "Bulgarian", "", "bg" }, + { "Burmese", "", "my" }, + { "Catalan", "", "ca" }, + { "Chamorro", "", "ch" }, + { "Chechen", "", "ce" }, + { "Chinese", "", "zh" }, + { "Church Slavic", "", "cu" }, + { "Chuvash", "", "cv" }, + { "Cornish", "", "kw" }, + { "Corsican", "", "co" }, + { "Czech", "", "cs" }, + { "Danish", "Dansk", "da" }, + { "Dutch", "Nederlands", "nl" }, + { "Dzongkha", "", "dz" }, + { "English", "English", "en" }, + { "Esperanto", "", "eo" }, + { "Estonian", "", "et" }, + { "Faroese", "", "fo" }, + { "Fijian", "", "fj" }, + { "Finnish", "Suomi", "fi" }, + { "French", "Francais", "fr" }, + { "Frisian", "", "fy" }, + { "Georgian", "", "ka" }, + { "German", "Deutsch", "de" }, + { "Gaelic (Scots)", "", "gd" }, + { "Irish", "", "ga" }, + { "Gallegan", "", "gl" }, + { "Manx", "", "gv" }, + { "Greek, Modern ()", "", "el" }, + { "Guarani", "", "gn" }, + { "Gujarati", "", "gu" }, + { "Hebrew", "", "he" }, + { "Herero", "", "hz" }, + { "Hindi", "", "hi" }, + { "Hiri Motu", "", "ho" }, + { "Hungarian", "Magyar", "hu" }, + { "Icelandic", "Islenska", "is" }, + { "Inuktitut", "", "iu" }, + { "Interlingue", "", "ie" }, + { "Interlingua", "", "ia" }, + { "Indonesian", "", "id" }, + { "Inupiaq", "", "ik" }, + { "Italian", "Italiano", "it" }, + { "Javanese", "", "jv" }, + { "Japanese", "", "ja" }, + { "Kalaallisut (Greenlandic)", "", "kl" }, + { "Kannada", "", "kn" }, + { "Kashmiri", "", "ks" }, + { "Kazakh", "", "kk" }, + { "Khmer", "", "km" }, + { "Kikuyu", "", "ki" }, + { "Kinyarwanda", "", "rw" }, + { "Kirghiz", "", "ky" }, + { "Komi", "", "kv" }, + { "Korean", "", "ko" }, + { "Kuanyama", "", "kj" }, + { "Kurdish", "", "ku" }, + { "Lao", "", "lo" }, + { "Latin", "", "la" }, + { "Latvian", "", "lv" }, + { "Lingala", "", "ln" }, + { "Lithuanian", "", "lt" }, + { "Letzeburgesch", "", "lb" }, + { "Macedonian", "", "mk" }, + { "Marshall", "", "mh" }, + { "Malayalam", "", "ml" }, + { "Maori", "", "mi" }, + { "Marathi", "", "mr" }, + { "Malay", "", "ms" }, + { "Malagasy", "", "mg" }, + { "Maltese", "", "mt" }, + { "Moldavian", "", "mo" }, + { "Mongolian", "", "mn" }, + { "Nauru", "", "na" }, + { "Navajo", "", "nv" }, + { "Ndebele, South", "", "nr" }, + { "Ndebele, North", "", "nd" }, + { "Ndonga", "", "ng" }, + { "Nepali", "", "ne" }, + { "Norwegian", "Norsk", "no" }, + { "Norwegian Nynorsk", "", "nn" }, + { "Norwegian Bokmål", "", "nb" }, + { "Chichewa; Nyanja", "", "ny" }, + { "Occitan (post 1500); Provençal", "", "oc" }, + { "Oriya", "", "or" }, + { "Oromo", "", "om" }, + { "Ossetian; Ossetic", "", "os" }, + { "Panjabi", "", "pa" }, + { "Persian", "", "fa" }, + { "Pali", "", "pi" }, + { "Polish", "", "pl" }, + { "Portuguese", "Portugues", "pt" }, + { "Pushto", "", "ps" }, + { "Quechua", "", "qu" }, + { "Raeto-Romance", "", "rm" }, + { "Romanian", "", "ro" }, + { "Rundi", "", "rn" }, + { "Russian", "", "ru" }, + { "Sango", "", "sg" }, + { "Sanskrit", "", "sa" }, + { "Serbian", "", "sr" }, + { "Croatian", "Hrvatski", "hr" }, + { "Sinhalese", "", "si" }, + { "Slovak", "", "sk" }, + { "Slovenian", "", "sl" }, + { "Northern Sami", "", "se" }, + { "Samoan", "", "sm" }, + { "Shona", "", "sn" }, + { "Sindhi", "", "sd" }, + { "Somali", "", "so" }, + { "Sotho, Southern", "", "st" }, + { "Spanish", "Espanol", "es" }, + { "Sardinian", "", "sc" }, + { "Swati", "", "ss" }, + { "Sundanese", "", "su" }, + { "Swahili", "", "sw" }, + { "Swedish", "Svenska", "sv" }, + { "Tahitian", "", "ty" }, + { "Tamil", "", "ta" }, + { "Tatar", "", "tt" }, + { "Telugu", "", "te" }, + { "Tajik", "", "tg" }, + { "Tagalog", "", "tl" }, + { "Thai", "", "th" }, + { "Tibetan", "", "bo" }, + { "Tigrinya", "", "ti" }, + { "Tonga (Tonga Islands)", "", "to" }, + { "Tswana", "", "tn" }, + { "Tsonga", "", "ts" }, + { "Turkish", "", "tr" }, + { "Turkmen", "", "tk" }, + { "Twi", "", "tw" }, + { "Uighur", "", "ug" }, + { "Ukrainian", "", "uk" }, + { "Urdu", "", "ur" }, + { "Uzbek", "", "uz" }, + { "Vietnamese", "", "vi" }, + { "Volapük", "", "vo" }, + { "Welsh", "", "cy" }, + { "Wolof", "", "wo" }, + { "Xhosa", "", "xh" }, + { "Yiddish", "", "yi" }, + { "Yoruba", "", "yo" }, + { "Zhuang", "", "za" }, + { "Zulu", "", "zu" }, + { NULL, NULL, NULL } }; + +#endif diff --git a/core/Manager.cpp b/core/Manager.cpp new file mode 100644 index 000000000..583bda36a --- /dev/null +++ b/core/Manager.cpp @@ -0,0 +1,707 @@ +/* $Id: Manager.cpp,v 1.47 2003/10/05 14:28:40 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 "Manager.h" +#include "Fifo.h" +#include "Scanner.h" +#include "DVDReader.h" +#include "MpegDemux.h" +#include "Mpeg2Decoder.h" +#include "Mpeg4Encoder.h" +#include "Ac3Decoder.h" +#include "Mp3Encoder.h" +#include "AviMuxer.h" +#include "Resizer.h" + +#include <ffmpeg/avcodec.h> + +/* Public methods */ + +HBManager::HBManager( bool debug ) + : HBThread( "manager" ) +{ + fPid = 0; + + fStopScan = false; + fStopRip = false; + fRipDone = false; + fError = false; + + fScanner = NULL; + + fStatus.fMode = HB_MODE_NEED_VOLUME; + fNeedUpdate = true; + + /* See Log() in Common.cpp */ + if( debug ) + { + setenv( "HB_DEBUG", "1", 1 ); + } + else + { + unsetenv( "HB_DEBUG" ); + } + + fCurTitle = NULL; + fCurAudio1 = NULL; + fCurAudio2 = NULL; + + /* Init ffmpeg's libavcodec */ + avcodec_init(); +// register_avcodec( &mpeg4_encoder ); + avcodec_register_all(); + + Run(); +} + +HBManager::~HBManager() +{ + /* Stop ripping if needed */ + StopRip(); + while( fStopRip ) + { + Snooze( 10000 ); + } + + Stop(); + + /* Stop scanning if needed */ + if( fScanner ) + { + delete fScanner; + } + + /* Remove temp files */ + char command[1024]; memset( command, 0, 1024 ); + sprintf( command, "rm -f /tmp/HB.%d.*", fPid ); + system( command ); +} + +void HBManager::DoWork() +{ + fPid = (int) getpid(); + + while( !fDie ) + { + /* Terminate dying threads */ + if( fStopScan ) + { + fStopScan = false; + + delete fScanner; + fScanner = NULL; + + if( fStatus.fTitleList && fStatus.fTitleList->CountItems() ) + { + fStatus.fMode = HB_MODE_READY_TO_RIP; + } + else + { + fStatus.fMode = HB_MODE_INVALID_VOLUME; + } + fNeedUpdate = true; + } + + if( fStopRip || fError ) + { + delete fCurTitle->fDVDReader; + delete fCurTitle->fMpegDemux; + delete fCurTitle->fMpeg2Decoder; + delete fCurTitle->fResizer; + delete fCurTitle->fMpeg4Encoder; + delete fCurTitle->fAviMuxer; + + if( fCurAudio1 ) + { + delete fCurAudio1->fAc3Decoder; + delete fCurAudio1->fMp3Encoder; + } + + if( fCurAudio2 ) + { + delete fCurAudio2->fAc3Decoder; + delete fCurAudio2->fMp3Encoder; + } + + delete fCurTitle->fPSFifo; + delete fCurTitle->fMpeg2Fifo; + delete fCurTitle->fRawFifo; + delete fCurTitle->fResizedFifo; + delete fCurTitle->fMpeg4Fifo; + + if( fCurAudio1 ) + { + delete fCurAudio1->fAc3Fifo; + delete fCurAudio1->fRawFifo; + delete fCurAudio1->fMp3Fifo; + } + + if( fCurAudio2 ) + { + delete fCurAudio2->fAc3Fifo; + delete fCurAudio2->fRawFifo; + delete fCurAudio2->fMp3Fifo; + } + + fStatus.fMode = fError ? HB_MODE_ERROR : HB_MODE_CANCELED; + fStopRip = false; + fError = false; + fNeedUpdate = true; + } + + if( fRipDone ) + { + /* This is UGLY ! */ + while( fCurTitle->fPSFifo->Size() || + fCurTitle->fMpeg2Fifo->Size() || + fCurTitle->fRawFifo->Size() || + fCurTitle->fResizedFifo->Size() || + ( fCurAudio1 && fCurAudio1->fAc3Fifo->Size() ) || + ( fCurAudio1 && fCurAudio1->fRawFifo->Size() ) || + ( fCurAudio2 && fCurAudio2->fAc3Fifo->Size() ) || + ( fCurAudio2 && fCurAudio2->fRawFifo->Size() ) ) + { + Snooze( 10000 ); + } + + while( fCurTitle->fMpeg4Fifo->Size() && + ( !fCurAudio1 || fCurAudio1->fMp3Fifo->Size() ) && + ( !fCurAudio2 || fCurAudio2->fMp3Fifo->Size() ) ) + { + Snooze( 10000 ); + } + + delete fCurTitle->fDVDReader; + delete fCurTitle->fMpegDemux; + delete fCurTitle->fMpeg2Decoder; + delete fCurTitle->fResizer; + delete fCurTitle->fMpeg4Encoder; + delete fCurTitle->fAviMuxer; + + if( fCurAudio1 ) + { + delete fCurAudio1->fAc3Decoder; + delete fCurAudio1->fMp3Encoder; + } + + if( fCurAudio2 ) + { + delete fCurAudio2->fAc3Decoder; + delete fCurAudio2->fMp3Encoder; + } + + delete fCurTitle->fPSFifo; + delete fCurTitle->fMpeg2Fifo; + delete fCurTitle->fRawFifo; + delete fCurTitle->fResizedFifo; + delete fCurTitle->fMpeg4Fifo; + + if( fCurAudio1 ) + { + delete fCurAudio1->fAc3Fifo; + delete fCurAudio1->fRawFifo; + delete fCurAudio1->fMp3Fifo; + } + + if( fCurAudio2 ) + { + delete fCurAudio2->fAc3Fifo; + delete fCurAudio2->fRawFifo; + delete fCurAudio2->fMp3Fifo; + } + + fStatus.fMode = HB_MODE_DONE; + fRipDone = false; + fNeedUpdate = true; + } + + Snooze( 10000 ); + } +} + +bool HBManager::NeedUpdate() +{ + if( fNeedUpdate ) + { + fNeedUpdate = false; + return true; + } + + return false; +} + +HBStatus HBManager::GetStatus() +{ + return fStatus; +} + +int HBManager::GetPid() +{ + return fPid; +} + +void HBManager::ScanVolumes( char * device ) +{ + if( !( fStatus.fMode & + ( HB_MODE_NEED_VOLUME | HB_MODE_INVALID_VOLUME ) ) ) + { + Log( "HBManager::ScanVolumes : current mode is %d, aborting", + fStatus.fMode ); + return; + } + + fScanner = new HBScanner( this, device ); + fScanner->Run(); + + fStatus.fMode = HB_MODE_SCANNING; + fStatus.fScannedVolume = strdup( device ); + fStatus.fScannedTitle = 0; + fNeedUpdate = true; +} + +void HBManager::StartRip( HBTitle * title, HBAudio * audio1, + HBAudio * audio2, char * file ) +{ + if( !title || !file ) + { + Log( "HBManager::StartRip : error (title = %p, file = %s)", + title, file ); + return; + } + + if( !( fStatus.fMode & ( HB_MODE_READY_TO_RIP | HB_MODE_DONE | + HB_MODE_CANCELED | HB_MODE_ERROR ) ) ) + { + Log( "HBManager::StartRip : current mode is %d, aborting", + fStatus.fMode ); + return; + } + + FixPictureSettings( title ); + + Log( "HBManager::StartRip : device: %s, title: %d", + title->fDevice, title->fIndex ); + Log( " - video : %dx%d -> %dx%d, bitrate = %d, 2-pass = %s", + title->fInWidth, title->fInHeight, + title->fOutWidth, title->fOutHeight, + title->fBitrate, title->fTwoPass ? "yes" : "no" ); + Log( " - cropping: top=%d, bottom=%d, left=%d, right=%d", + title->fTopCrop, title->fBottomCrop, + title->fLeftCrop, title->fRightCrop ); + if( audio1 ) + { + Log( " - audio 1: lang = %s (%x), bitrate = %d", + audio1->fDescription, audio1->fId, audio1->fOutBitrate ); + } + if( audio2 ) + { + Log( " - audio 2: lang = %s (%x), bitrate = %d", + audio2->fDescription, audio1->fId, audio2->fOutBitrate ); + } + + /* Create fifos & threads */ + + title->fPSFifo = new HBFifo(); + title->fMpeg2Fifo = new HBFifo(); + title->fRawFifo = new HBFifo(); + title->fResizedFifo = new HBFifo(); + title->fMpeg4Fifo = new HBFifo(); + + title->fDVDReader = new HBDVDReader( this, title ); + title->fMpegDemux = new HBMpegDemux( this, title, audio1, + audio2 ); + title->fMpeg2Decoder = new HBMpeg2Decoder( this, title ); + title->fResizer = new HBResizer( this, title ); + title->fMpeg4Encoder = new HBMpeg4Encoder( this, title ); + title->fAviMuxer = new HBAviMuxer( this, title, audio1, audio2, + file ); + + if( audio1 ) + { + audio1->fAc3Fifo = new HBFifo(); + audio1->fRawFifo = new HBFifo(); + audio1->fMp3Fifo = new HBFifo(); + audio1->fAc3Decoder = new HBAc3Decoder( this, audio1 ); + audio1->fMp3Encoder = new HBMp3Encoder( this, audio1 ); + } + + if( audio2 ) + { + audio2->fAc3Fifo = new HBFifo(); + audio2->fRawFifo = new HBFifo(); + audio2->fMp3Fifo = new HBFifo(); + audio2->fAc3Decoder = new HBAc3Decoder( this, audio2 ); + audio2->fMp3Encoder = new HBMp3Encoder( this, audio2 ); + } + + /* Launch the threads */ + + title->fDVDReader->Run(); + title->fMpegDemux->Run(); + title->fMpeg2Decoder->Run(); + title->fResizer->Run(); + title->fMpeg4Encoder->Run(); + title->fAviMuxer->Run(); + + if( audio1 ) + { + audio1->fAc3Decoder->Run(); + audio1->fMp3Encoder->Run(); + } + + if( audio2 ) + { + audio2->fAc3Decoder->Run(); + audio2->fMp3Encoder->Run(); + } + + fCurTitle = title; + fCurAudio1 = audio1; + fCurAudio2 = audio2; + + fStatus.fMode = HB_MODE_ENCODING; + fStatus.fPosition = 0; + fStatus.fFrameRate = 0; + fStatus.fFrames = 0; + fStatus.fStartDate = 0; + fStatus.fRemainingTime = 0; + fStatus.fSuspendDate = 0; + fNeedUpdate = true; +} + +void HBManager::SuspendRip() +{ + if( fStatus.fMode != HB_MODE_ENCODING ) + { + Log( "HBManager::SuspendRip : current mode is %d, aborting", + fStatus.fMode ); + return; + } + + fCurTitle->fDVDReader->Suspend(); + fCurTitle->fMpegDemux->Suspend(); + fCurTitle->fMpeg2Decoder->Suspend(); + fCurTitle->fResizer->Suspend(); + fCurTitle->fMpeg4Encoder->Suspend(); + fCurTitle->fAviMuxer->Suspend(); + + if( fCurAudio1 ) + { + fCurAudio1->fAc3Decoder->Suspend(); + fCurAudio1->fMp3Encoder->Suspend(); + } + + if( fCurAudio2 ) + { + fCurAudio2->fAc3Decoder->Suspend(); + fCurAudio2->fMp3Encoder->Suspend(); + } + + fStatus.fMode = HB_MODE_SUSPENDED; + fStatus.fSuspendDate = GetDate(); + fNeedUpdate = true; +} + +void HBManager::ResumeRip() +{ + if( fStatus.fMode != HB_MODE_SUSPENDED ) + { + Log( "HBManager::ResumeRip : current mode is %d, aborting", + fStatus.fMode ); + return; + } + + fCurTitle->fDVDReader->Resume(); + fCurTitle->fMpegDemux->Resume(); + fCurTitle->fMpeg2Decoder->Resume(); + fCurTitle->fResizer->Resume(); + fCurTitle->fMpeg4Encoder->Resume(); + fCurTitle->fAviMuxer->Resume(); + + if( fCurAudio1 ) + { + fCurAudio1->fAc3Decoder->Resume(); + fCurAudio1->fMp3Encoder->Resume(); + } + + if( fCurAudio2 ) + { + fCurAudio2->fAc3Decoder->Resume(); + fCurAudio2->fMp3Encoder->Resume(); + } + + fStatus.fMode = HB_MODE_ENCODING; + fStatus.fStartDate += GetDate() - fStatus.fSuspendDate; + fNeedUpdate = true; +} + +void HBManager::StopRip() +{ + if( !( fStatus.fMode & ( HB_MODE_ENCODING | HB_MODE_SUSPENDED ) ) ) + { + Log( "HBManager::StopRip : current mode is %d, aborting", + fStatus.fMode ); + return; + } + + /* Stop the threads */ + + fCurTitle->fDVDReader->Stop(); + fCurTitle->fMpegDemux->Stop(); + fCurTitle->fMpeg2Decoder->Stop(); + fCurTitle->fMpeg4Encoder->Stop(); + fCurTitle->fAviMuxer->Stop(); + + if( fCurAudio1 ) + { + fCurAudio1->fAc3Decoder->Stop(); + fCurAudio1->fMp3Encoder->Stop(); + } + + if( fCurAudio2 ) + { + fCurAudio2->fAc3Decoder->Stop(); + fCurAudio2->fMp3Encoder->Stop(); + } + + fStopRip = true; +} + +#define fInWidth title->fInWidth +#define fInHeight title->fInHeight +#define fAspect title->fAspect +#define fDeinterlace title->fDeinterlace +#define fOutWidth title->fOutWidth +#define fOutHeight title->fOutHeight +#define fOutWidthMax title->fOutWidthMax +#define fOutHeightMax title->fOutHeightMax +#define fTopCrop title->fTopCrop +#define fBottomCrop title->fBottomCrop +#define fLeftCrop title->fLeftCrop +#define fRightCrop title->fRightCrop + +void HBManager::FixPictureSettings( HBTitle * title ) +{ + /* Sanity checks */ + fTopCrop = EVEN( fTopCrop ); + fBottomCrop = EVEN( fBottomCrop ); + fLeftCrop = EVEN( fLeftCrop ); + fRightCrop = EVEN( fRightCrop ); + + fOutWidth = MIN( fOutWidth, fOutWidthMax ); + fOutWidth = MAX( 16, fOutWidth ); + + fOutHeight = MULTIPLE_16( (uint64_t) fOutWidth * fInWidth * + ( fInHeight - fTopCrop - fBottomCrop ) * + VOUT_ASPECT_FACTOR / + ( (uint64_t) fInHeight * + ( fInWidth - fLeftCrop - fRightCrop ) * + fAspect ) ); + fOutHeight = MAX( 16, fOutHeight ); + + if( fOutHeight > fOutHeightMax ) + { + fOutHeight = fOutHeightMax; + fOutWidth = MULTIPLE_16( (uint64_t) fOutHeight * fInHeight * + ( fInWidth - fLeftCrop - fRightCrop ) * + fAspect / + ( (uint64_t) fInWidth * + ( fInHeight - fTopCrop - fBottomCrop ) * + VOUT_ASPECT_FACTOR ) ); + fOutWidth = MIN( fOutWidth, fOutWidthMax ); + fOutWidth = MAX( 16, fOutWidth ); + } +} + +uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image ) +{ + FixPictureSettings( title ); + + AVPicture pic1, pic2, pic3, pic4; + uint8_t * buf1, * buf2, * buf3, * buf4; + + /* Original YUV picture */ + buf1 = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 ); + avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, fInWidth, + fInHeight ); + + /* Deinterlaced YUV picture */ + buf2 = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 ); + avpicture_fill( &pic2, buf2, PIX_FMT_YUV420P, + fInWidth, fInHeight ); + + /* Resized YUV picture */ + buf3 = (uint8_t*) malloc( 3 * fOutWidth * fOutHeight / 2 ); + avpicture_fill( &pic3, buf3, PIX_FMT_YUV420P, fOutWidth, + fOutHeight ); + + /* Resized RGB picture ) */ + buf4 = (uint8_t*) malloc( 4 * fOutWidth * fOutHeight ); + avpicture_fill( &pic4, buf4, PIX_FMT_RGBA32, fOutWidth, + fOutHeight ); + + /* Get the original image from the temp file */ + char fileName[1024]; memset( fileName, 0, 1024 ); + sprintf( fileName, "/tmp/HB.%d.%x.%d", fPid, (uint32_t) title, + image); + FILE * file = fopen( fileName, "r" ); + fread( buf1, 3 * fInWidth * fInHeight / 2, 1, file ); + fclose( file ); + + /* Deinterlace if needed, and resize */ + ImgReSampleContext * resampleContext = + img_resample_full_init( fOutWidth, fOutHeight, + fInWidth, fInHeight, + fTopCrop, fBottomCrop, + fLeftCrop, fRightCrop ); + if( fDeinterlace ) + { + avpicture_deinterlace( &pic2, &pic1, PIX_FMT_YUV420P, + fInWidth, fInHeight ); + img_resample( resampleContext, &pic3, &pic2 ); + } + else + { + img_resample( resampleContext, &pic3, &pic1 ); + } + + /* Convert to RGB */ + img_convert( &pic4, PIX_FMT_RGBA32, &pic3, PIX_FMT_YUV420P, + fOutWidth, fOutHeight ); + + /* Create the final preview */ + uint8_t * preview = (uint8_t*) malloc( 4 * ( fOutWidthMax + 2 ) * + ( fOutHeightMax + 2 ) ); + + /* Blank it */ + memset( preview, 0, + 4 * ( fOutWidthMax + 2 ) * ( fOutHeightMax + 2 ) ); + + /* Draw the picture (centered) and draw the cropping zone */ + uint32_t leftOffset = 1 + ( fOutWidthMax - fOutWidth ) / 2; + uint32_t topOffset = 1 + ( fOutHeightMax - fOutHeight ) / 2; + + memset( preview + 4 * ( ( fOutWidthMax + 2 ) * ( topOffset - 1 ) + + leftOffset - 1 ), + 0xFF, 4 * ( fOutWidth + 2 ) ); + + for( uint32_t i = 0; i < fOutHeight; i++ ) + { + memset( preview + 4 * ( ( fOutWidthMax + 2 ) * + ( i + topOffset ) + leftOffset - 1 ), + 0xFF, 4 ); + memcpy( preview + 4 * ( ( fOutWidthMax + 2 ) * + ( i + topOffset ) + leftOffset ), + buf4 + 4 * fOutWidth * i, + 4 * fOutWidth ); + memset( preview + 4 * ( ( fOutWidthMax + 2 ) * + ( i + topOffset ) + leftOffset + + fOutWidth ), + 0xFF, 4 ); + } + + memset( preview + 4 * ( ( fOutWidthMax + 2 ) * + ( topOffset + fOutHeight ) + + leftOffset - 1 ), + 0xFF, 4 * ( fOutWidth + 2 ) ); + + /* Free memory */ + free( buf1 ); + free( buf2 ); + free( buf3 ); + free( buf4 ); + + return preview; +} + +#undef fInWidth +#undef fInHeight +#undef fAspect +#undef fDeinterlace +#undef fOutWidth +#undef fOutHeight +#undef fOutWidthMax +#undef fOutHeightMax +#undef fTopCrop +#undef fBottomCrop +#undef fLeftCrop +#undef fRightCrop + +void HBManager::Scanning( char * volume, int title ) +{ + fStatus.fMode = HB_MODE_SCANNING; + fStatus.fScannedVolume = volume; + fStatus.fScannedTitle = title; + fNeedUpdate = true; +} + +void HBManager::ScanDone( HBList * titleList ) +{ + fStatus.fTitleList = titleList;; + fStopScan = true; +} + +/* Called by the DVD reader */ +void HBManager::Done() +{ + fRipDone = true; +} + +void HBManager::Error() +{ + if( fStatus.fMode != HB_MODE_ENCODING ) + { + return; + } + + /* Stop the threads */ + + fCurTitle->fDVDReader->Stop(); + fCurTitle->fMpegDemux->Stop(); + fCurTitle->fMpeg2Decoder->Stop(); + fCurTitle->fResizer->Stop(); + fCurTitle->fMpeg4Encoder->Stop(); + fCurTitle->fAviMuxer->Stop(); + + if( fCurAudio1 ) + { + fCurAudio1->fAc3Decoder->Stop(); + fCurAudio1->fMp3Encoder->Stop(); + } + + if( fCurAudio2 ) + { + fCurAudio2->fAc3Decoder->Stop(); + fCurAudio2->fMp3Encoder->Stop(); + } + + fError = true; +} + +void HBManager::SetPosition( float pos ) +{ + if( !fStatus.fStartDate ) + { + fStatus.fStartDate = GetDate(); + } + + fStatus.fFrames++; + + if( ( pos - fStatus.fPosition ) * 10000 < 1 ) + { + return; + } + + fStatus.fPosition = pos; + fStatus.fFrameRate = (float) fStatus.fFrames / + ( ( (float) ( GetDate() - fStatus.fStartDate ) ) / 1000000 ) ; + fStatus.fRemainingTime = + (uint32_t) ( (float) ( GetDate() - fStatus.fStartDate ) * + ( 1 - fStatus.fPosition ) / + ( 1000000 * fStatus.fPosition ) ); + fNeedUpdate = true; +} + diff --git a/core/Manager.h b/core/Manager.h new file mode 100644 index 000000000..8aa6cec3a --- /dev/null +++ b/core/Manager.h @@ -0,0 +1,61 @@ +/* $Id: Manager.h,v 1.27 2003/09/30 21:21:32 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. */ + +#ifndef HB_MANAGER_H +#define HB_MANAGER_H + +#include "Common.h" +#include "Thread.h" + +class HBManager : public HBThread +{ + public: + HBManager( bool debug = false ); + ~HBManager(); + void DoWork(); + + /* Methods called by the interface */ + bool NeedUpdate(); + HBStatus GetStatus(); + void ScanVolumes( char * device ); + void StartRip( HBTitle * title, HBAudio * audio1, + HBAudio * audio2, char * file ); + void SuspendRip(); + void ResumeRip(); + void StopRip(); + uint8_t * GetPreview( HBTitle * title, uint32_t image ); + + /* Methods called by the working threads */ + int GetPid(); + void Scanning( char * volume, int title ); + void ScanDone( HBList * titleList ); + void Done(); + void Error(); + void SetPosition( float pos ); + + private: + void FixPictureSettings( HBTitle * title ); + + int fPid; + + /* Booleans used in DoWork() */ + bool fStopScan; + volatile bool fStopRip; + bool fRipDone; + bool fError; + + /* Scanner thread */ + HBScanner * fScanner; + + /* Status infos */ + bool fNeedUpdate; + HBStatus fStatus; + HBTitle * fCurTitle; + HBAudio * fCurAudio1; + HBAudio * fCurAudio2; +}; + +#endif diff --git a/HBMp3Encoder.cpp b/core/Mp3Encoder.cpp index cff6d6d66..b4e9fe860 100644 --- a/HBMp3Encoder.cpp +++ b/core/Mp3Encoder.cpp @@ -1,47 +1,57 @@ -/* $Id: HBMp3Encoder.cpp,v 1.6 2003/08/25 20:41:51 titer Exp $ */ +/* $Id: Mp3Encoder.cpp,v 1.7 2003/09/30 14:38:15 titer Exp $ -#include "HBCommon.h" -#include "HBMp3Encoder.h" -#include "HBManager.h" -#include "HBFifo.h" + 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 "Mp3Encoder.h" +#include "Manager.h" +#include "Fifo.h" #include <lame/lame.h> -HBMp3Encoder::HBMp3Encoder( HBManager * manager, HBAudioInfo * audioInfo ) +HBMp3Encoder::HBMp3Encoder( HBManager * manager, HBAudio * audio ) : HBThread( "mp3encoder" ) { fManager = manager; - fAudioInfo = audioInfo; - + fAudio = audio; + fRawBuffer = NULL; fPosInBuffer = 0; fLeftSamples = NULL; fRightSamples = NULL; + + fPosition = 0; } void HBMp3Encoder::DoWork() { /* Wait a first buffer so we are sure that - fAudioInfo->fInSampleRate (set the AC3 decoder) is not garbage */ - while( !fDie && !fAudioInfo->fRawFifo->Size() ) + fAudio->fInSampleRate (set the AC3 decoder) is not garbage */ + while( !fDie && !fAudio->fRawFifo->Size() ) + { + Snooze( 5000 ); + } + + if( fDie ) { - snooze( 5000 ); + return; } - + /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by output buffer. As we are resampling from fInSampleRate to fOutSampleRate, we will give ( 1152 * fInSampleRate ) / ( 2 * fOutSampleRate ) to libmp3lame so we are sure we will never get more than 1 frame at a time */ - uint32_t count = ( 1152 * fAudioInfo->fInSampleRate ) / - ( 2 * fAudioInfo->fOutSampleRate ); + uint32_t count = ( 1152 * fAudio->fInSampleRate ) / + ( 2 * fAudio->fOutSampleRate ); /* Init libmp3lame */ lame_global_flags * globalFlags = lame_init(); - lame_set_in_samplerate( globalFlags, fAudioInfo->fInSampleRate ); - lame_set_out_samplerate( globalFlags, fAudioInfo->fOutSampleRate ); - lame_set_brate( globalFlags, fAudioInfo->fOutBitrate ); - + lame_set_in_samplerate( globalFlags, fAudio->fInSampleRate ); + lame_set_out_samplerate( globalFlags, fAudio->fOutSampleRate ); + lame_set_brate( globalFlags, fAudio->fOutBitrate ); + if( lame_init_params( globalFlags ) == -1 ) { Log( "HBMp3Encoder::DoWork() : lame_init_params() failed" ); @@ -53,20 +63,26 @@ void HBMp3Encoder::DoWork() fRightSamples = (float*) malloc( count * sizeof( float ) ); HBBuffer * mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); - int ret; - while( !fDie ) + + int ret; + for( ;; ) { + while( fSuspend ) + { + Snooze( 10000 ); + } + /* Get new samples */ if( !GetSamples( count ) ) { - continue; + break; } ret = lame_encode_buffer_float( globalFlags, fLeftSamples, fRightSamples, count, mp3Buffer->fData, mp3Buffer->fSize ); - + if( ret < 0 ) { /* Something wrong happened */ @@ -77,18 +93,19 @@ void HBMp3Encoder::DoWork() else if( ret > 0 ) { /* We got something, send it to the muxer */ - mp3Buffer->fSize = ret; + mp3Buffer->fSize = ret; mp3Buffer->fKeyFrame = true; - fAudioInfo->fMp3Fifo->Push( mp3Buffer ); + mp3Buffer->fPosition = fPosition; + Push( fAudio->fMp3Fifo, mp3Buffer ); mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); } } - + /* Clean up */ delete mp3Buffer; free( fLeftSamples ); free( fRightSamples ); - + lame_close( globalFlags ); } @@ -100,34 +117,33 @@ bool HBMp3Encoder::GetSamples( uint32_t count ) { if( !fRawBuffer ) { - fRawBuffer = fAudioInfo->fRawFifo->Pop(); - - if( !fRawBuffer ) + if( !( fRawBuffer = Pop( fAudio->fRawFifo ) ) ) { return false; } - + fPosInBuffer = 0; + fPosition = fRawBuffer->fPosition; } - + int willCopy = MIN( count - samplesNb, 6 * 256 - fPosInBuffer ); - + memcpy( fLeftSamples + samplesNb, (float*) fRawBuffer->fData + fPosInBuffer, willCopy * sizeof( float ) ); memcpy( fRightSamples + samplesNb, (float*) fRawBuffer->fData + 6 * 256 + fPosInBuffer, willCopy * sizeof( float ) ); - - samplesNb += willCopy; + + samplesNb += willCopy; fPosInBuffer += willCopy; - + if( fPosInBuffer == 6 * 256 ) { delete fRawBuffer; fRawBuffer = NULL; } } - + return true; } diff --git a/core/Mp3Encoder.h b/core/Mp3Encoder.h new file mode 100644 index 000000000..67b8647d5 --- /dev/null +++ b/core/Mp3Encoder.h @@ -0,0 +1,34 @@ +/* $Id: Mp3Encoder.h,v 1.5 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. */ + +#ifndef HB_MP3_ENCODER_H +#define HB_MP3_ENCODER_H + +#include "Common.h" +#include "Thread.h" + +class HBMp3Encoder : public HBThread +{ + public: + HBMp3Encoder( HBManager * manager, + HBAudio * audio ); + + private: + void DoWork(); + bool GetSamples( uint32_t count ); + + HBManager * fManager; + HBAudio * fAudio; + + HBBuffer * fRawBuffer; + uint32_t fPosInBuffer; /* in samples */ + float * fLeftSamples; + float * fRightSamples; + + float fPosition; +}; + +#endif diff --git a/core/Mpeg2Decoder.cpp b/core/Mpeg2Decoder.cpp new file mode 100644 index 000000000..1ba4945bc --- /dev/null +++ b/core/Mpeg2Decoder.cpp @@ -0,0 +1,137 @@ +/* $Id: Mpeg2Decoder.cpp,v 1.14 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 "Mpeg2Decoder.h" +#include "Manager.h" +#include "Fifo.h" + +extern "C" { +#include <mpeg2dec/mpeg2.h> +} +#include <ffmpeg/avcodec.h> + +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; +} + diff --git a/core/Mpeg2Decoder.h b/core/Mpeg2Decoder.h new file mode 100644 index 000000000..2e1a46b3d --- /dev/null +++ b/core/Mpeg2Decoder.h @@ -0,0 +1,34 @@ +/* $Id: Mpeg2Decoder.h,v 1.10 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. */ + +#ifndef HB_MPEG2_DECODER_H +#define HB_MPEG2_DECODER_H + +#include "Common.h" +#include "Thread.h" + +class HBMpeg2Decoder : public HBThread +{ + public: + HBMpeg2Decoder( HBManager * manager, + HBTitle * title ); + + private: + void DoWork(); + void Init(); + void Close(); + void DecodeBuffer(); + + HBManager * fManager; + HBTitle * fTitle; + + uint32_t fPass; + HBBuffer * fMpeg2Buffer; + mpeg2dec_t * fHandle; + bool fLateField; +}; + +#endif 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 ); + } +} + diff --git a/core/Mpeg4Encoder.h b/core/Mpeg4Encoder.h new file mode 100644 index 000000000..1bdb29434 --- /dev/null +++ b/core/Mpeg4Encoder.h @@ -0,0 +1,36 @@ +/* $Id: Mpeg4Encoder.h,v 1.8 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. */ + +#ifndef HB_MPEG4_ENCODER_H +#define HB_MPEG4_ENCODER_H + +#include "Common.h" +#include "Thread.h" + +class HBMpeg4Encoder : public HBThread +{ + public: + HBMpeg4Encoder( HBManager * manager, + HBTitle * title ); + + private: + void DoWork(); + void Init(); + void Close(); + void EncodeBuffer(); + + HBManager * fManager; + HBTitle * fTitle; + + uint32_t fPass; + HBBuffer * fResizedBuffer; + AVCodecContext * fContext; + AVFrame * fFrame; + FILE * fFile; + char * fLog; +}; + +#endif diff --git a/HBMpegDemux.cpp b/core/MpegDemux.cpp index 5fda3dde3..d3fd6b089 100644 --- a/HBMpegDemux.cpp +++ b/core/MpegDemux.cpp @@ -1,27 +1,30 @@ -/* $Id: HBMpegDemux.cpp,v 1.13 2003/08/24 19:28:18 titer Exp $ */ +/* $Id: MpegDemux.cpp,v 1.10 2003/10/04 12:12:48 titer Exp $ -#include "HBCommon.h" -#include "HBManager.h" -#include "HBMpegDemux.h" -#include "HBFifo.h" + 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 "MpegDemux.h" +#include "Manager.h" +#include "Fifo.h" extern "C" { #include <a52dec/a52.h> } -HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitleInfo * titleInfo, - HBAudioInfo * audio1Info, HBAudioInfo * audio2Info ) +HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitle * title, + HBAudio * audio1, HBAudio * audio2 ) : HBThread( "mpegdemux" ) { fManager = manager; - fTitleInfo = titleInfo; - fAudio1Info = audio1Info; - fAudio2Info = audio2Info; - + fTitle = title; + fAudio1 = audio1; + fAudio2 = audio2; + fPSBuffer = NULL; fESBuffer = NULL; fESBufferList = NULL; - + fFirstVideoPTS = -1; fFirstAudio1PTS = -1; fFirstAudio2PTS = -1; @@ -29,28 +32,37 @@ HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitleInfo * titleInfo, void HBMpegDemux::DoWork() { - while( !fDie ) + for( ;; ) { + while( fSuspend ) + { + Snooze( 10000 ); + } + /* Get a PS packet */ - fPSBuffer = fTitleInfo->fPSFifo->Pop(); - - if( !fPSBuffer ) + if( !( fPSBuffer = Pop( fTitle->fPSFifo ) ) ) { - continue; + break; } - + /* Get the ES data in it */ - fESBufferList = PStoES( fPSBuffer ); - + PStoES( fPSBuffer, &fESBufferList ); + if( !fESBufferList ) { continue; } - + while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) ) { fESBufferList->RemoveItem( fESBuffer ); - + + if( fESBuffer->fPass == 1 && fESBuffer->fStreamId != 0xE0 ) + { + delete fESBuffer; + continue; + } + /* Look for a decoder for this ES */ if( fESBuffer->fStreamId == 0xE0 ) { @@ -58,43 +70,47 @@ void HBMpegDemux::DoWork() { fFirstVideoPTS = fESBuffer->fPTS; } - fTitleInfo->fMpeg2Fifo->Push( fESBuffer ); + Push( fTitle->fMpeg2Fifo, fESBuffer ); } - else if( fESBuffer->fStreamId == fAudio1Info->fId ) + else if( fAudio1 && + fESBuffer->fStreamId == fAudio1->fId ) { /* If the audio track starts later than the video, repeat the first frame as long as needed */ if( fFirstAudio1PTS < 0 ) { fFirstAudio1PTS = fESBuffer->fPTS; - + if( fFirstAudio1PTS > fFirstVideoPTS ) { - Log( "HBMpegDemux::DoWork() : audio track %x is late", - fAudio1Info->fId ); + Log( "HBMpegDemux::DoWork() : audio track %x " + "is late (%lld)", fAudio1->fId, + fFirstAudio1PTS - fFirstVideoPTS ); InsertSilence( fFirstAudio1PTS - fFirstVideoPTS, - fAudio1Info->fAc3Fifo, + fAudio1->fAc3Fifo, fESBuffer ); } } - fAudio1Info->fAc3Fifo->Push( fESBuffer ); + Push( fAudio1->fAc3Fifo, fESBuffer ); } - else if( fESBuffer->fStreamId == fAudio2Info->fId ) + else if( fAudio2 && + fESBuffer->fStreamId == fAudio2->fId ) { if( fFirstAudio2PTS < 0 ) { fFirstAudio2PTS = fESBuffer->fPTS; - + if( fFirstAudio2PTS > fFirstVideoPTS ) { - Log( "HBMpegDemux::DoWork() : audio track %x is late", - fAudio2Info->fId ); + Log( "HBMpegDemux::DoWork() : audio track %x " + "is late (%lld)", fAudio2->fId, + fFirstAudio2PTS - fFirstVideoPTS ); InsertSilence( fFirstAudio2PTS - fFirstVideoPTS, - fAudio2Info->fAc3Fifo, + fAudio2->fAc3Fifo, fESBuffer ); } } - fAudio2Info->fAc3Fifo->Push( fESBuffer ); + Push( fAudio2->fAc3Fifo, fESBuffer ); } else { @@ -113,31 +129,38 @@ void HBMpegDemux::InsertSilence( int64_t time, HBFifo * fifo, int bitrate = 0; int frameSize = a52_syncinfo( buffer->fData, &flags, &sampleRate, &bitrate ); - + if( !frameSize ) { Log( "HBMpegDemux::InsertSilence() : a52_syncinfo() failed" ); return; } - - uint32_t samples = sampleRate * time / 90000; + + uint32_t frames = ( ( sampleRate * time / 90000 ) + ( 3 * 256 ) ) + / ( 6 * 256 ); + + if( !frames ) + { + return; + } + + Log( "HBMpegDemux::InsertSilence() : adding %d frames", frames ); + HBBuffer * buffer2; - - Log( "HBMpegDemux::InsertSilence() : adding %d samples", samples ); - - for( uint32_t i = 0; i < samples / ( 6 * 256 ); i++ ) + for( uint32_t i = 0; i < frames; i++ ) { buffer2 = new HBBuffer( frameSize ); + buffer2->fPosition = buffer->fPosition; memcpy( buffer2->fData, buffer->fData, frameSize ); - fifo->Push( buffer2 ); + Push( fifo, buffer2 ); } } -BList * PStoES( HBBuffer * psBuffer ) +bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList ) { #define psData (psBuffer->fData) - BList * esBufferList = new BList(); + HBList * esBufferList = new HBList(); HBBuffer * esBuffer; uint32_t pos = 0; @@ -149,23 +172,24 @@ BList * PStoES( HBBuffer * psBuffer ) psData[pos] << 24, psData[pos+1] << 16, psData[pos+2] << 8, psData[pos+3] ); delete psBuffer; - return NULL; + (*_esBufferList) = NULL; + return false; } pos += 4; /* pack_start_code */ pos += 9; /* pack_header */ pos += 1 + ( psData[pos] & 0x7 ); /* stuffing bytes */ - + /* system_header */ if( psData[pos] == 0 && psData[pos+1] == 0 && psData[pos+2] == 0x1 && psData[pos+3] == 0xBB ) { uint32_t header_length; - + pos += 4; /* system_header_start_code */ header_length = ( psData[pos] << 8 ) + psData[pos+1]; pos += 2 + header_length; } - + /* PES */ while( pos + 2 < psBuffer->fSize && psData[pos] == 0 && psData[pos+1] == 0 && psData[pos+2] == 0x1 ) @@ -177,7 +201,7 @@ BList * PStoES( HBBuffer * psBuffer ) uint32_t PES_header_end; bool hasPTS; uint64_t PTS = 0; - + pos += 3; /* packet_start_code_prefix */ streamId = psData[pos++]; @@ -187,11 +211,11 @@ BList * PStoES( HBBuffer * psBuffer ) hasPTS = ( ( psData[pos+1] >> 6 ) & 0x2 ); pos += 2; /* Required headers */ - + PES_header_data_length = psData[pos]; pos += 1; PES_header_end = pos + PES_header_data_length; - + if( hasPTS ) { PTS = ( ( ( psData[pos] >> 1 ) & 0x7 ) << 30 ) + @@ -200,45 +224,47 @@ BList * PStoES( HBBuffer * psBuffer ) ( psData[pos+3] << 7 ) + ( psData[pos+4] >> 1 ); } - + pos = PES_header_end; - + if( streamId != 0xE0 && streamId != 0xBD ) { /* Not interesting */ continue; } - + if( streamId == 0xBD ) { /* A52 : don't ask */ streamId |= ( psData[pos] << 8 ); pos += 4; } - + /* Here we hit we ES payload */ esBuffer = new HBBuffer( PES_packet_end - pos ); - + esBuffer->fPosition = psBuffer->fPosition; + esBuffer->fPass = psBuffer->fPass; esBuffer->fStreamId = streamId; esBuffer->fPTS = PTS; memcpy( esBuffer->fData, psBuffer->fData + pos, PES_packet_end - pos ); - + esBufferList->AddItem( esBuffer ); - + pos = PES_packet_end; } - + delete psBuffer; - + if( esBufferList && !esBufferList->CountItems() ) { delete esBufferList; - return NULL; + esBufferList = NULL; } - return esBufferList; + (*_esBufferList) = esBufferList; + return true; #undef psData } diff --git a/core/MpegDemux.h b/core/MpegDemux.h new file mode 100644 index 000000000..ef5b1b3d9 --- /dev/null +++ b/core/MpegDemux.h @@ -0,0 +1,40 @@ +/* $Id: MpegDemux.h,v 1.6 2003/10/04 12:12:48 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. */ + +#ifndef HB_MPEG_DEMUX_H +#define HB_MPEG_DEMUX_H + +#include "Common.h" +#include "Thread.h" + +bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList ); + +class HBMpegDemux : public HBThread +{ + public: + HBMpegDemux( HBManager * manager, HBTitle * title, + HBAudio * audio1, HBAudio * audio2 ); + + private: + void DoWork(); + void InsertSilence( int64_t time, HBFifo * fifo, + HBBuffer * buffer ); + + HBManager * fManager; + HBTitle * fTitle; + HBAudio * fAudio1; + HBAudio * fAudio2; + + HBBuffer * fPSBuffer; + HBBuffer * fESBuffer; + HBList * fESBufferList; + + int64_t fFirstVideoPTS; + int64_t fFirstAudio1PTS; + int64_t fFirstAudio2PTS; +}; + +#endif diff --git a/core/Resizer.cpp b/core/Resizer.cpp new file mode 100644 index 000000000..e3cae3986 --- /dev/null +++ b/core/Resizer.cpp @@ -0,0 +1,89 @@ +/* $Id: Resizer.cpp,v 1.3 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 "Resizer.h" +#include "Manager.h" +#include "Fifo.h" + +#include <ffmpeg/avcodec.h> + +HBResizer::HBResizer( HBManager * manager, HBTitle * title ) + : HBThread( "resizer" ) +{ + fManager = manager; + fTitle = title; +} + +void HBResizer::DoWork() +{ + /* Init libavcodec */ + ImgReSampleContext * resampleContext = + img_resample_full_init( fTitle->fOutWidth, fTitle->fOutHeight, + fTitle->fInWidth, fTitle->fInHeight, + fTitle->fTopCrop, fTitle->fBottomCrop, + fTitle->fLeftCrop, fTitle->fRightCrop ); + + /* Buffers & pictures */ + HBBuffer * rawBuffer, * deinterlacedBuffer, * resizedBuffer; + AVPicture rawPicture, deinterlacedPicture, resizedPicture; + + deinterlacedBuffer = new HBBuffer( 3 * fTitle->fInWidth * + fTitle->fInHeight / 2 ); + avpicture_fill( &deinterlacedPicture, deinterlacedBuffer->fData, + PIX_FMT_YUV420P, fTitle->fInWidth, + fTitle->fInHeight ); + + for( ;; ) + { + while( fSuspend ) + { + Snooze( 10000 ); + } + + if( !( rawBuffer = Pop( fTitle->fRawFifo ) ) ) + { + break; + } + + avpicture_fill( &rawPicture, rawBuffer->fData, + PIX_FMT_YUV420P, fTitle->fInWidth, + fTitle->fInHeight ); + + resizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth * + fTitle->fOutHeight / 2 ); + resizedBuffer->fPosition = rawBuffer->fPosition; + resizedBuffer->fPass = rawBuffer->fPass; + avpicture_fill( &resizedPicture, resizedBuffer->fData, + PIX_FMT_YUV420P, fTitle->fOutWidth, + fTitle->fOutHeight ); + + + if( fTitle->fDeinterlace ) + { + avpicture_deinterlace( &deinterlacedPicture, &rawPicture, + PIX_FMT_YUV420P, + fTitle->fInWidth, + fTitle->fInHeight ); + img_resample( resampleContext, &resizedPicture, + &deinterlacedPicture ); + } + else + { + img_resample( resampleContext, &resizedPicture, + &rawPicture ); + } + + Push( fTitle->fResizedFifo, resizedBuffer ); + delete rawBuffer; + } + + /* Free memory */ + delete deinterlacedBuffer; + + /* Close libavcodec */ + img_resample_close( resampleContext ); +} + diff --git a/core/Resizer.h b/core/Resizer.h new file mode 100644 index 000000000..1fdde85d3 --- /dev/null +++ b/core/Resizer.h @@ -0,0 +1,25 @@ +/* $Id: Resizer.h,v 1.2 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. */ + +#ifndef HB_RESIZER_H +#define HB_RESIZER_H + +#include "Common.h" +#include "Thread.h" + +class HBResizer : public HBThread +{ + public: + HBResizer( HBManager * manager, HBTitle * title ); + + private: + void DoWork(); + + HBManager * fManager; + HBTitle * fTitle; +}; + +#endif diff --git a/core/Scanner.cpp b/core/Scanner.cpp new file mode 100644 index 000000000..575b25573 --- /dev/null +++ b/core/Scanner.cpp @@ -0,0 +1,275 @@ +/* $Id: Scanner.cpp,v 1.18 2003/10/04 12:12:48 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 "Scanner.h" +#include "Manager.h" +#include "Fifo.h" +#include "MpegDemux.h" + +#include <dvdread/ifo_types.h> +#include <dvdplay/dvdplay.h> +#include <dvdplay/info.h> +#include <dvdplay/state.h> +#include <dvdplay/nav.h> + +extern "C" { +#include <mpeg2dec/mpeg2.h> +} + +HBScanner::HBScanner( HBManager * manager, char * device ) + : HBThread( "scanner" ) +{ + fManager = manager; + fDevice = strdup( device ); +} + +void HBScanner::DoWork() +{ + Log( "HBScanner::DoWork() : opening device %s", fDevice ); + + dvdplay_ptr vmg; + vmg = dvdplay_open( fDevice, NULL, NULL ); + if( !vmg ) + { + Log( "HBScanner::DoWork() : dvdplay_open() failed (%s)", + fDevice ); + fManager->ScanDone( NULL ); + return; + } + + /* Detect titles */ + HBList * titleList = new HBList(); + HBTitle * title; + for( int i = 0; i < dvdplay_title_nr( vmg ); i++ ) + { + if( fDie ) + { + break; + } + + Log( "HBScanner::DoWork() : scanning title %d", i + 1 ); + fManager->Scanning( fDevice, i + 1 ); + + title = new HBTitle( fDevice, i + 1 ); + + if( ScanTitle( title, vmg ) ) + { + titleList->AddItem( title ); + } + else + { + Log( "HBScanner::DoWork() : ignoring title %d", i + 1 ); + delete title; + } + } + + Log( "HBScanner::DoWork() : closing device %s", fDevice ); + dvdplay_close( vmg ); + + fManager->ScanDone( titleList ); +} + +bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg ) +{ + dvdplay_start( vmg, title->fIndex ); + + /* Length */ + title->fLength = dvdplay_title_time( vmg ); + Log( "HBScanner::ScanTitle() : title length is %lld seconds", + title->fLength ); + + /* Discard titles under 10 seconds */ + if( title->fLength < 10 ) + { + return false; + } + + /* Detect languages */ + int audio_nr, foo; + dvdplay_audio_info( vmg, &audio_nr, &foo ); + + audio_attr_t * attr; + HBAudio * audio; + for( int i = 0; i < audio_nr; i++ ) + { + if( fDie ) + { + break; + } + + int id = dvdplay_audio_id( vmg, i ); + if( id > 0 ) + { + if( ( id & 0xFF ) != 0xBD ) + { + Log( "HBScanner::ScanTitle() : non-AC3 audio track " + "detected, ignoring" ); + continue; + } + attr = dvdplay_audio_attr( vmg, i ); + audio = new HBAudio( id, LanguageForCode( attr->lang_code ) ); + Log( "HBScanner::ScanTitle() : new language (%x, %s)", + id, audio->fDescription ); + title->fAudioList->AddItem( audio ); + } + } + + /* Discard titles with no audio tracks */ + if( !title->fAudioList->CountItems() ) + { + return false; + } + + /* Kludge : libdvdplay wants we to read a first block before seeking */ + uint8_t dummyBuf[DVD_VIDEO_LB_LEN]; + dvdplay_read( vmg, dummyBuf, 1 ); + + for( int i = 0; i < 10; i++ ) + { + if( fDie ) + { + break; + } + + if( !DecodeFrame( title, vmg, i ) ) + { + return false; + } + } + + if( title->fInHeight * title->fAspect > + title->fInWidth * VOUT_ASPECT_FACTOR ) + { + title->fOutWidthMax = title->fInWidth; + title->fOutHeightMax = MULTIPLE_16( (uint64_t)title->fInWidth * + VOUT_ASPECT_FACTOR / title->fAspect ); + } + else + { + title->fOutWidthMax = MULTIPLE_16( (uint64_t)title->fInHeight * + title->fAspect / VOUT_ASPECT_FACTOR ); + title->fOutHeightMax = title->fInHeight; + } + + /* Default picture size */ + title->fOutWidth = title->fOutWidthMax; + title->fOutHeight = title->fOutHeightMax; + + return true; +} +bool HBScanner::DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i ) +{ + /* Seek to the right place */ + int titleFirst = dvdplay_title_first ( vmg ); + int titleEnd = dvdplay_title_end( vmg ); + + dvdplay_seek( vmg, ( i + 1 ) * ( titleEnd - titleFirst ) / 11 ) ; + + /* Init libmpeg2 */ + mpeg2dec_t * handle = mpeg2_init(); + const mpeg2_info_t * info = mpeg2_info( handle ); + mpeg2_state_t state; + + /* Init the destination file */ + char fileName[1024]; + memset( fileName, 0, 1024 ); + sprintf( fileName, "/tmp/HB.%d.%x.%d", fManager->GetPid(), + (uint32_t) title, i ); + FILE * file = fopen( fileName, "w" ); + + HBList * esBufferList = NULL; + HBBuffer * psBuffer = NULL; + HBBuffer * esBuffer = NULL; + + for( ;; ) + { + state = mpeg2_parse( handle ); + + if( state == STATE_BUFFER ) + { + /* Free the previous buffer */ + if( esBuffer ) + { + delete esBuffer; + esBuffer = NULL; + } + + /* Get a new one */ + while( !esBuffer ) + { + while( !esBufferList ) + { + psBuffer = new HBBuffer( DVD_VIDEO_LB_LEN ); + if( dvdplay_read( vmg, psBuffer->fData, 1 ) != 1 || + !PStoES( psBuffer, &esBufferList ) ) + { + Log( "HBScanner::DecodeFrame : failed to get " + "a valid PS packet" ); + mpeg2_close( handle ); + fclose( file ); + return false; + } + } + + esBuffer = (HBBuffer*) esBufferList->ItemAt( 0 ); + esBufferList->RemoveItem( esBuffer ); + if( !esBufferList->CountItems() ) + { + delete esBufferList; + esBufferList = NULL; + } + + if( esBuffer->fStreamId != 0xE0 ) + { + delete esBuffer; + esBuffer = NULL; + } + } + + /* Feed libmpeg2 */ + mpeg2_buffer( handle, esBuffer->fData, + esBuffer->fData + esBuffer->fSize ); + } + else if( state == STATE_SEQUENCE ) + { + /* Get size & framerate info */ + title->fInWidth = info->sequence->width; + title->fInHeight = info->sequence->height; + title->fAspect = (uint64_t)info->sequence->display_width * + info->sequence->pixel_width * VOUT_ASPECT_FACTOR / + ( info->sequence->display_height * + info->sequence->pixel_height ); + title->fRate = 27000000; + title->fScale = info->sequence->frame_period; + } + else if( ( state == STATE_SLICE || state == STATE_END ) && + ( info->display_fbuf ) && + ( info->display_picture->flags & PIC_MASK_CODING_TYPE ) + == PIC_FLAG_CODING_TYPE_I ) + { + /* Write the raw picture to a file */ + fwrite( info->display_fbuf->buf[0], + title->fInWidth * title->fInHeight, 1, file ); + fwrite( info->display_fbuf->buf[1], + title->fInWidth * title->fInHeight / 4, 1, file ); + fwrite( info->display_fbuf->buf[2], + title->fInWidth * title->fInHeight / 4, 1, file ); + break; + } + else if( state == STATE_INVALID ) + { + /* Reset libmpeg2 */ + mpeg2_close( handle ); + handle = mpeg2_init(); + } + } + + mpeg2_close( handle ); + + fclose( file ); + + return true; +} diff --git a/core/Scanner.h b/core/Scanner.h new file mode 100644 index 000000000..dbdb587c4 --- /dev/null +++ b/core/Scanner.h @@ -0,0 +1,27 @@ +/* $Id: Scanner.h,v 1.5 2003/09/30 21:21:32 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. */ + +#ifndef HB_SCANNER_H +#define HB_SCANNER_H + +#include "Common.h" +#include "Thread.h" + +class HBScanner : public HBThread +{ + public: + HBScanner( HBManager * manager, char * device ); + + private: + void DoWork(); + bool ScanTitle( HBTitle * title, dvdplay_ptr vmg ); + bool DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i ); + + HBManager * fManager; + char * fDevice; +}; + +#endif diff --git a/core/Thread.cpp b/core/Thread.cpp new file mode 100644 index 000000000..43f058cad --- /dev/null +++ b/core/Thread.cpp @@ -0,0 +1,171 @@ +/* $Id: Thread.cpp,v 1.19 2003/10/01 21:17:17 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. */ + +#if defined( SYS_BEOS ) +# include <OS.h> +# include <Locker.h> +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +# include <pthread.h> +#endif + +#include "Thread.h" +#include "Fifo.h" + +HBThread::HBThread( char * name, int priority ) +{ + fName = strdup( name ); + fPriority = priority; + fDie = false; + fSuspend = false; +} + +HBThread::~HBThread() +{ + fDie = true; + fSuspend = false; + +#if defined( SYS_BEOS ) + long exit_value; + wait_for_thread( fThread, &exit_value ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_join( fThread, NULL ); +#endif + + Log( "Thread %d stopped (\"%s\")", fThread, fName ); + free( fName ); +} + +void HBThread::Run() +{ +#if defined( SYS_BEOS ) + fThread = spawn_thread( (int32 (*)(void *)) ThreadFunc, + fName, fPriority, this ); + resume_thread( fThread ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_create( &fThread, NULL, + (void * (*)(void *)) ThreadFunc, this ); +#if 0 +#if defined( SYS_MACOSX ) + int policy; + struct sched_param param; + memset( ¶m, 0, sizeof( struct sched_param ) ); + if( fPriority < 0 ) + { + param.sched_priority = (-1) * fPriority; + policy = SCHED_OTHER; + } + else + { + param.sched_priority = fPriority; + policy = SCHED_RR; + } + if ( pthread_setschedparam( fThread, policy, ¶m ) ) + { + Log( "HBThread::Run : couldn't set thread priority" ); + } +#endif +#endif +#endif + + Log( "Thread %d started (\"%s\")", fThread, fName ); +} + +void HBThread::Stop() +{ + Log( "Stopping thread %d (\"%s\")", fThread, fName ); + + fDie = true; + fSuspend = false; +} + +void HBThread::Suspend() +{ + fSuspend = true; +} + +void HBThread::Resume() +{ + fSuspend = false; +} + +bool HBThread::Push( HBFifo * fifo, HBBuffer * buffer ) +{ + while( !fDie ) + { + if( fifo->Push( buffer ) ) + { + return true; + } + + Snooze( 10000 ); + } + + delete buffer; + return false; +} + +HBBuffer * HBThread::Pop( HBFifo * fifo ) +{ + HBBuffer * buffer; + + while( !fDie ) + { + if( ( buffer = fifo->Pop() ) ) + { + return buffer; + } + + Snooze( 10000 ); + } + + return NULL; +} + +void HBThread::ThreadFunc( HBThread * _this ) +{ + _this->DoWork(); +} + +void HBThread::DoWork() +{ +} + + +HBLock::HBLock() +{ +#if defined( SYS_BEOS ) + fLocker = new BLocker(); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_init( &fMutex, NULL ); +#endif +} + +HBLock::~HBLock() +{ +#if defined( SYS_BEOS ) + delete fLocker; +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_destroy( &fMutex ); +#endif +} + +void HBLock::Lock() +{ +#if defined( SYS_BEOS ) + fLocker->Lock(); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_lock( &fMutex ); +#endif +} + +void HBLock::Unlock() +{ +#if defined( SYS_BEOS ) + fLocker->Unlock(); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_unlock( &fMutex ); +#endif +} diff --git a/core/Thread.h b/core/Thread.h new file mode 100644 index 000000000..6afd59f53 --- /dev/null +++ b/core/Thread.h @@ -0,0 +1,76 @@ +/* $Id: Thread.h,v 1.16 2003/10/01 21:17:17 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. */ + +#ifndef HB_THREAD_H +#define HB_THREAD_H + +#include "Common.h" + +#if defined( SYS_BEOS ) +# define HB_LOW_PRIORITY 5 +# define HB_NORMAL_PRIORITY 10 +#elif defined( SYS_MACOSX ) +# define HB_LOW_PRIORITY (-47) +# define HB_NORMAL_PRIORITY (-47) /* FIXME */ +#elif defined( SYS_LINUX ) +/* Actually unused */ +# define HB_LOW_PRIORITY 0 +# define HB_NORMAL_PRIORITY 0 +#endif + +class HBThread +{ + public: + HBThread( char * name, + int priority = HB_LOW_PRIORITY ); + virtual ~HBThread(); + void Run(); + void Stop(); + void Suspend(); + void Resume(); + + protected: + bool Push( HBFifo * fifo, HBBuffer * buffer ); + HBBuffer * Pop( HBFifo * fifo ); + + volatile bool fDie; + volatile bool fSuspend; + + private: + static void ThreadFunc( HBThread * _this ); + virtual void DoWork(); + + char * fName; + int fPriority; + +#if defined( SYS_BEOS ) + int fThread; +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_t fThread; +#endif +}; + +#if defined( SYS_BEOS ) +class BLocker; +#endif + +class HBLock +{ + public: + HBLock(); + ~HBLock(); + void Lock(); + void Unlock(); + + private: +#if defined( SYS_BEOS ) + BLocker * fLocker; +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_t fMutex; +#endif +}; + +#endif diff --git a/macosx/English.lproj/InfoPlist.strings b/macosx/English.lproj/InfoPlist.strings Binary files differnew file mode 100644 index 000000000..ae4f04858 --- /dev/null +++ b/macosx/English.lproj/InfoPlist.strings diff --git a/macosx/English.lproj/MainMenu.nib/classes.nib b/macosx/English.lproj/MainMenu.nib/classes.nib new file mode 100644 index 000000000..df2438f40 --- /dev/null +++ b/macosx/English.lproj/MainMenu.nib/classes.nib @@ -0,0 +1,70 @@ +{ + IBClasses = ( + {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, + { + ACTIONS = { + BrowseDVD = id; + BrowseFile = id; + Cancel = id; + ClosePanel = id; + NextPicture = id; + PreviousPicture = id; + Resume = id; + Rip = id; + Scan = id; + ScanEnableIntf = id; + ShowPicturePanel = id; + Suspend = id; + UpdatePicture = id; + UpdatePopUp = id; + }; + CLASS = HBController; + LANGUAGE = ObjC; + OUTLETS = { + fAudioField = NSTextField; + fAudioPopUp = NSPopUpButton; + fAudioStepper = NSStepper; + fBlankView = NSView; + fBottomField = NSTextField; + fBottomStepper = NSStepper; + fCropButton = NSButton; + fDVDFolderField = NSTextField; + fDVDPopUp = NSPopUpButton; + fDeinterlaceCheck = NSButton; + fDonePanel = NSPanel; + fFileField = NSTextField; + fInfoField = NSTextField; + fLeftField = NSTextField; + fLeftStepper = NSStepper; + fPictureGLView = PictureGLView; + fPicturePanel = NSPanel; + fRightField = NSTextField; + fRightStepper = NSStepper; + fRipBrowseButton = NSButton; + fRipButton = NSButton; + fRipProgress = NSProgressIndicator; + fRipStatusField = NSTextField; + fRipView = NSView; + fScanBrowseButton = NSButton; + fScanButton = NSButton; + fScanMatrix = NSMatrix; + fScanProgress = NSProgressIndicator; + fScanStatusField = NSTextField; + fScanView = NSView; + fSuspendButton = NSButton; + fTitlePopUp = NSPopUpButton; + fTopField = NSTextField; + fTopStepper = NSStepper; + fTwoPassCheck = NSButton; + fVideoField = NSTextField; + fVideoStepper = NSStepper; + fWidthField = NSTextField; + fWidthStepper = NSStepper; + fWindow = NSWindow; + }; + SUPERCLASS = NSObject; + }, + {CLASS = PictureGLView; LANGUAGE = ObjC; SUPERCLASS = NSOpenGLView; } + ); + IBVersion = 1; +}
\ No newline at end of file diff --git a/macosx/English.lproj/MainMenu.nib/info.nib b/macosx/English.lproj/MainMenu.nib/info.nib new file mode 100644 index 000000000..0dbd97023 --- /dev/null +++ b/macosx/English.lproj/MainMenu.nib/info.nib @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>IBDocumentLocation</key> + <string>109 136 381 380 0 0 1440 878 </string> + <key>IBEditorPositions</key> + <dict> + <key>249</key> + <string>510 472 420 258 0 0 1440 878 </string> + <key>256</key> + <string>454 372 420 466 0 0 1440 878 </string> + <key>29</key> + <string>407 469 205 44 0 0 1440 878 </string> + </dict> + <key>IBFramework Version</key> + <string>291.0</string> + <key>IBOpenObjects</key> + <array> + <integer>249</integer> + <integer>256</integer> + <integer>21</integer> + <integer>434</integer> + <integer>29</integer> + </array> + <key>IBSystem Version</key> + <string>6R73</string> +</dict> +</plist> diff --git a/macosx/English.lproj/MainMenu.nib/objects.nib b/macosx/English.lproj/MainMenu.nib/objects.nib Binary files differnew file mode 100644 index 000000000..a7849eb54 --- /dev/null +++ b/macosx/English.lproj/MainMenu.nib/objects.nib diff --git a/macosx/HBController.h b/macosx/HBController.h new file mode 100644 index 000000000..2e3339c74 --- /dev/null +++ b/macosx/HBController.h @@ -0,0 +1,88 @@ +/* $Id: HBController.h,v 1.19 2003/10/06 21:13:45 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 <Cocoa/Cocoa.h> + +#include "Manager.h" +#include "PictureGLView.h" + +@interface HBController : NSObject + +{ + IBOutlet NSWindow * fWindow; + + IBOutlet NSView * fScanView; + IBOutlet NSMatrix * fScanMatrix; + IBOutlet NSPopUpButton * fDVDPopUp; + IBOutlet NSTextField * fDVDFolderField; + IBOutlet NSButton * fScanBrowseButton; + IBOutlet NSTextField * fScanStatusField; + IBOutlet NSProgressIndicator * fScanProgress; + IBOutlet NSButton * fScanButton; + + IBOutlet NSView * fRipView; + IBOutlet NSPopUpButton * fTitlePopUp; + IBOutlet NSPopUpButton * fAudioPopUp; + IBOutlet NSTextField * fVideoField; + IBOutlet NSStepper * fVideoStepper; + IBOutlet NSTextField * fAudioField; + IBOutlet NSStepper * fAudioStepper; + IBOutlet NSButton * fTwoPassCheck; + IBOutlet NSButton * fCropButton; + IBOutlet NSTextField * fFileField; + IBOutlet NSButton * fRipBrowseButton; + IBOutlet NSTextField * fRipStatusField; + IBOutlet NSProgressIndicator * fRipProgress; + IBOutlet NSButton * fSuspendButton; + IBOutlet NSButton * fRipButton; + IBOutlet NSPanel * fDonePanel; + + IBOutlet NSPanel * fPicturePanel; + IBOutlet PictureGLView * fPictureGLView; + IBOutlet NSTextField * fWidthField; + IBOutlet NSStepper * fWidthStepper; + IBOutlet NSButton * fDeinterlaceCheck; + IBOutlet NSTextField * fTopField; + IBOutlet NSStepper * fTopStepper; + IBOutlet NSTextField * fBottomField; + IBOutlet NSStepper * fBottomStepper; + IBOutlet NSTextField * fLeftField; + IBOutlet NSStepper * fLeftStepper; + IBOutlet NSTextField * fRightField; + IBOutlet NSStepper * fRightStepper; + IBOutlet NSTextField * fInfoField; + int fPicture; + + IBOutlet NSView * fBlankView; + HBManager * fManager; + HBList * fTitleList; +} + +- (IBAction) BrowseDVD: (id) sender; +- (void) BrowseDVDDone: (NSOpenPanel *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo; +- (IBAction) Scan: (id) sender; + +- (IBAction) BrowseFile: (id) sender; +- (void) BrowseFileDone: (NSSavePanel *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo; +- (IBAction) ShowPicturePanel: (id) sender; +- (IBAction) ClosePanel: (id) sender; +- (IBAction) Rip: (id) sender; +- (IBAction) Cancel: (id) sender; +- (IBAction) Suspend: (id) sender; +- (IBAction) Resume: (id) sender; + +- (IBAction) PreviousPicture: (id) sender; +- (IBAction) NextPicture: (id) sender; +- (IBAction) UpdatePicture: (id) sender; + +- (void) UpdateIntf: (NSTimer *) timer; +- (void) DetectDrives; +- (void) ScanEnableIntf: (id) sender; +- (void) UpdatePopUp: (id) sender; + +@end diff --git a/macosx/HBController.mm b/macosx/HBController.mm new file mode 100644 index 000000000..f46d0221a --- /dev/null +++ b/macosx/HBController.mm @@ -0,0 +1,627 @@ +/* $Id: HBController.mm,v 1.24 2003/10/06 21:13:45 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 <paths.h> +#include <IOKit/IOKitLib.h> +#include <IOKit/IOBSD.h> +#include <IOKit/storage/IOMedia.h> +#include <IOKit/storage/IODVDMedia.h> + +#include "HBController.h" +#include "Manager.h" + +@implementation HBController + +- (void) applicationDidFinishLaunching: (NSNotification *) notification +{ + /* Init libhb */ + fManager = new HBManager( true ); + + /* Update the GUI every 1/10 sec */ + [NSTimer scheduledTimerWithTimeInterval: 0.1 + target: self selector: @selector( UpdateIntf: ) + userInfo: nil repeats: FALSE]; +} + +- (NSApplicationTerminateReply) applicationShouldTerminate: + (NSApplication *) app +{ + /* Clean up */ + delete fManager; + + return NSTerminateNow; +} + +- (void) awakeFromNib +{ + [[fScanMatrix cellAtRow: 0 column: 0] + setAction: @selector( ScanEnableIntf: )]; + [[fScanMatrix cellAtRow: 0 column: 0] setTarget: self]; + [[fScanMatrix cellAtRow: 1 column: 0] + setAction: @selector( ScanEnableIntf: )]; + [[fScanMatrix cellAtRow: 1 column: 0] setTarget: self]; + [fScanProgress setStyle: NSProgressIndicatorSpinningStyle]; + [fScanProgress setDisplayedWhenStopped: NO]; + [fRipProgress setIndeterminate: NO]; + [fTitlePopUp removeAllItems]; + [fAudioPopUp removeAllItems]; + + char string[1024]; memset( string, 0, 1024 ); + snprintf( string, 1024, "%s/Desktop/Movie.avi", getenv( "HOME" ) ); + [fFileField setStringValue: [NSString stringWithCString: string]]; + + /* Show the scan view */ + [fWindow setContentSize: [fScanView frame].size]; + [fWindow setContentView: fScanView]; + [fWindow center]; + + /* Detect DVD drives */ + [self DetectDrives]; + [self ScanEnableIntf: self]; + + /* Init a blank view, used in window resizing animation */ + fBlankView = [[NSView alloc] init]; +} + +- (BOOL) windowShouldClose: (id) sender +{ + /* Stop the application when the user closes the window */ + [NSApp terminate: self]; + return YES; +} + +- (IBAction) BrowseDVD: (id) sender +{ + /* Open a panel to let the user choose and update the text field */ + NSOpenPanel * panel = [NSOpenPanel openPanel]; + + [panel setAllowsMultipleSelection: NO]; + [panel setCanChooseFiles: NO]; + [panel setCanChooseDirectories: YES ]; + + [panel beginSheetForDirectory: nil file: nil types: nil + modalForWindow: fWindow modalDelegate: self + didEndSelector: @selector( BrowseDVDDone:returnCode:contextInfo: ) + contextInfo: nil]; +} + +- (void) BrowseDVDDone: (NSOpenPanel *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo +{ + if( returnCode == NSOKButton ) + { + [fDVDFolderField setStringValue: + [[sheet filenames] objectAtIndex: 0]]; + } +} + +- (IBAction) BrowseFile: (id) sender +{ + /* Open a panel to let the user choose and update the text field */ + NSSavePanel * panel = [NSSavePanel savePanel]; + + [panel beginSheetForDirectory: nil file: nil + modalForWindow: fWindow modalDelegate: self + didEndSelector: @selector( BrowseFileDone:returnCode:contextInfo: ) + contextInfo: nil]; +} + +- (void) BrowseFileDone: (NSSavePanel *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo +{ + if( returnCode == NSOKButton ) + { + [fFileField setStringValue: [sheet filename]]; + } +} + +- (IBAction) Scan: (id) sender +{ + /* Ask the manager to start scanning the specified volume */ + + if( ![fScanMatrix selectedRow] ) + { + /* DVD drive */ + fManager->ScanVolumes( (char*) [[fDVDPopUp titleOfSelectedItem] + cString] ); + } + else + { + /* DVD folder */ + fManager->ScanVolumes( (char*) [[fDVDFolderField stringValue] + cString] ); + } +} + +- (IBAction) ShowPicturePanel: (id) sender +{ + HBTitle * title = (HBTitle*) + fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); + + [fPictureGLView SetManager: fManager]; + [fPictureGLView SetTitle: title]; + + fPicture = 0; + [fPictureGLView ShowPicture: fPicture]; + + [fWidthStepper setValueWraps: NO]; + [fWidthStepper setIncrement: 16]; + [fWidthStepper setMinValue: 16]; + [fWidthStepper setMaxValue: title->fOutWidthMax]; + [fWidthStepper setIntValue: title->fOutWidth]; + [fWidthField setIntValue: title->fOutWidth]; + [fTopStepper setValueWraps: NO]; + [fTopStepper setIncrement: 2]; + [fTopStepper setMinValue: 0]; + [fTopStepper setMaxValue: title->fInHeight / 4]; + [fTopStepper setIntValue: title->fTopCrop]; + [fTopField setIntValue: title->fTopCrop]; + [fBottomStepper setValueWraps: NO]; + [fBottomStepper setIncrement: 2]; + [fBottomStepper setMinValue: 0]; + [fBottomStepper setMaxValue: title->fInHeight / 4]; + [fBottomStepper setIntValue: title->fBottomCrop]; + [fBottomField setIntValue: title->fBottomCrop]; + [fLeftStepper setValueWraps: NO]; + [fLeftStepper setIncrement: 2]; + [fLeftStepper setMinValue: 0]; + [fLeftStepper setMaxValue: title->fInWidth / 4]; + [fLeftStepper setIntValue: title->fLeftCrop]; + [fLeftField setIntValue: title->fLeftCrop]; + [fRightStepper setValueWraps: NO]; + [fRightStepper setIncrement: 2]; + [fRightStepper setMinValue: 0]; + [fRightStepper setMaxValue: title->fInWidth / 4]; + [fRightStepper setIntValue: title->fRightCrop]; + [fRightField setIntValue: title->fRightCrop]; + + char string[1024]; memset( string, 0, 1024 ); + sprintf( string, "Final size: %dx%d", + title->fOutWidth, title->fOutHeight ); + [fInfoField setStringValue: [NSString stringWithCString: string]]; + + /* Resize the panel */ + NSSize newSize; + /* XXX */ + newSize.width = 762 /*fPicturePanelSize.width*/ + + title->fOutWidthMax - 720; + newSize.height = 754 /*fPicturePanelSize.height*/ + + title->fOutHeightMax - 576; + [fPicturePanel setContentSize: newSize]; + + [NSApp beginSheet: fPicturePanel + modalForWindow: fWindow + modalDelegate: nil + didEndSelector: nil + contextInfo: nil]; + [NSApp runModalForWindow: fPicturePanel]; + [NSApp endSheet: fPicturePanel]; + [fPicturePanel orderOut: self]; +} + +- (IBAction) ClosePanel: (id) sender +{ + [NSApp stopModal]; +} + +- (IBAction) Rip: (id) sender +{ + /* Rip or Cancel ? */ + if( [[fRipButton title] compare: @"Cancel" ] == NSOrderedSame ) + { + [self Cancel: self]; + return; + } + + /* Get the specified title & audio track(s) */ + HBTitle * title = (HBTitle*) + fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); + HBAudio * audio = (HBAudio*) + title->fAudioList->ItemAt( [fAudioPopUp indexOfSelectedItem] ); + + /* Use user settings */ + title->fBitrate = [fVideoStepper intValue]; + audio->fOutBitrate = [fAudioStepper intValue]; + title->fTwoPass = ( [fTwoPassCheck state] == NSOnState ); + + /* Let libhb do the job */ + fManager->StartRip( title, audio, NULL, + (char*) [[fFileField stringValue] cString] ); +} + +- (IBAction) Cancel: (id) sender +{ + fManager->StopRip(); +} + +- (IBAction) Suspend: (id) sender +{ + if( [[fSuspendButton title] compare: @"Resume" ] == NSOrderedSame ) + { + [self Resume: self]; + return; + } + + fManager->SuspendRip(); +} + +- (IBAction) Resume: (id) sender +{ + fManager->ResumeRip(); +} + +- (IBAction) PreviousPicture: (id) sender +{ + if( fPicture > 0 ) + { + fPicture--; + [fPictureGLView ShowPicture: fPicture]; + } +} + +- (IBAction) NextPicture: (id) sender +{ + if( fPicture < 9 ) + { + fPicture++; + [fPictureGLView ShowPicture: fPicture]; + } +} + +- (IBAction) UpdatePicture: (id) sender +{ + HBTitle * title = (HBTitle*) + fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); + title->fOutWidth = [fWidthStepper intValue]; + title->fDeinterlace = ( [fDeinterlaceCheck state] == NSOnState ); + title->fTopCrop = [fTopStepper intValue]; + title->fBottomCrop = [fBottomStepper intValue]; + title->fLeftCrop = [fLeftStepper intValue]; + title->fRightCrop = [fRightStepper intValue]; + + [fPictureGLView ShowPicture: fPicture]; + + [fWidthStepper setIntValue: title->fOutWidth]; + [fTopStepper setIntValue: title->fTopCrop]; + [fBottomStepper setIntValue: title->fBottomCrop]; + [fLeftStepper setIntValue: title->fLeftCrop]; + [fRightStepper setIntValue: title->fRightCrop]; + [fWidthField setIntValue: [fWidthStepper intValue]]; + [fTopField setIntValue: [fTopStepper intValue]]; + [fBottomField setIntValue: [fBottomStepper intValue]]; + [fLeftField setIntValue: [fLeftStepper intValue]]; + [fRightField setIntValue: [fRightStepper intValue]]; + + char string[1024]; memset( string, 0, 1024 ); + sprintf( string, "Final size: %dx%d", + title->fOutWidth, title->fOutHeight ); + [fInfoField setStringValue: [NSString stringWithCString: string]]; +} + +- (void) UpdateIntf: (NSTimer *) timer +{ + /* Ask libhb about what's happening now */ + if( fManager->NeedUpdate() ) + { + HBStatus status = fManager->GetStatus(); + + switch( status.fMode ) + { + case HB_MODE_NEED_VOLUME: + break; + + case HB_MODE_SCANNING: + { + [fScanMatrix setEnabled: NO]; + [fDVDPopUp setEnabled: NO]; + [fDVDFolderField setEnabled: NO]; + [fScanBrowseButton setEnabled: NO]; + [fScanProgress startAnimation: self]; + [fScanButton setEnabled: NO]; + + char string[1024]; memset( string, 0, 1024 ); + if( status.fScannedTitle ) + { + sprintf( string, "Scanning %s, title %d...", + status.fScannedVolume, + status.fScannedTitle ); + } + else + { + sprintf( string, "Opening %s...", + status.fScannedVolume ); + } + [fScanStatusField setStringValue: + [NSString stringWithCString: string]]; + + break; + } + + case HB_MODE_INVALID_VOLUME: + { + [fScanMatrix setEnabled: YES]; + [self ScanEnableIntf: self]; + [fScanProgress stopAnimation: self]; + [fScanButton setEnabled: YES]; + + [fScanStatusField setStringValue: + @"Invalid volume, try again" ]; + break; + } + + case HB_MODE_READY_TO_RIP: + { + fTitleList = status.fTitleList; + + /* Show a temporary empty view while the window + resizing animation */ + [fWindow setContentView: fBlankView ]; + + /* Actually resize it */ + NSRect newFrame; + newFrame = [NSWindow contentRectForFrameRect: [fWindow frame] + styleMask: [fWindow styleMask]]; + newFrame.origin.y += newFrame.size.height - + [fRipView frame].size.height; + newFrame.size.height = [fRipView frame].size.height; + newFrame.size.width = [fRipView frame].size.width; + newFrame = [NSWindow frameRectForContentRect: newFrame + styleMask: [fWindow styleMask]]; + [fWindow setFrame: newFrame display: YES animate: YES]; + + /* Show the new GUI */ + [fWindow setContentView: fRipView ]; + [fSuspendButton setEnabled: NO]; + + HBTitle * title; + for( uint32_t i = 0; i < fTitleList->CountItems(); i++ ) + { + title = (HBTitle*) fTitleList->ItemAt( i ); + char string[1024]; memset( string, 0, 1024 ); + sprintf( string, "%d (%02lld:%02lld:%02lld)", + title->fIndex, title->fLength / 3600, + ( title->fLength % 3600 ) / 60, + title->fLength % 60 ); + [[fTitlePopUp menu] addItemWithTitle: + [NSString stringWithCString: string] + action: @selector( UpdatePopUp: ) + keyEquivalent: @""]; + } + [self UpdatePopUp: self]; + + break; + } + + case HB_MODE_ENCODING: + { + [fTitlePopUp setEnabled: NO]; + [fAudioPopUp setEnabled: NO]; + [fVideoField setEnabled: NO]; + [fVideoStepper setEnabled: NO]; + [fAudioField setEnabled: NO]; + [fAudioStepper setEnabled: NO]; + [fTwoPassCheck setEnabled: NO]; + [fCropButton setEnabled: NO]; + [fFileField setEnabled: NO]; + [fRipBrowseButton setEnabled: NO]; + [fRipButton setTitle: @"Cancel"]; + [fSuspendButton setEnabled: YES]; + [fSuspendButton setTitle: @"Suspend"]; + + if( !status.fPosition ) + { + [fRipStatusField setStringValue: @"Starting..."]; + [fRipProgress setIndeterminate: YES]; + [fRipProgress startAnimation: self];; + } + else + { + char string[1024]; memset( string, 0, 1024 ); + sprintf( string, "Encoding: %.2f %%, %.2f fps " + "(%02d:%02d:%02d remaining)", + 100 * status.fPosition, status.fFrameRate, + status.fRemainingTime / 3600, + ( status.fRemainingTime % 3600 ) / 60, + status.fRemainingTime % 60 ); + [fRipStatusField setStringValue: + [NSString stringWithCString: string]]; + [fRipProgress setIndeterminate: NO]; + [fRipProgress setDoubleValue: 100 * status.fPosition]; + } + + break; + } + + case HB_MODE_SUSPENDED: + { + char string[1024]; memset( string, 0, 1024 ); + sprintf( string, "Encoding: %.2f %%, %.2f fps (PAUSED)", + 100 * status.fPosition, status.fFrameRate) ; + [fRipStatusField setStringValue: + [NSString stringWithCString: string]]; + + [fRipProgress setDoubleValue: 100 * status.fPosition]; + + [fSuspendButton setTitle: @"Resume"]; + break; + } + + case HB_MODE_DONE: + case HB_MODE_CANCELED: + case HB_MODE_ERROR: + [fTitlePopUp setEnabled: YES]; + [fAudioPopUp setEnabled: YES]; + [fVideoField setEnabled: YES]; + [fVideoStepper setEnabled: YES]; + [fAudioField setEnabled: YES]; + [fAudioStepper setEnabled: YES]; + [fTwoPassCheck setEnabled: YES]; + [fCropButton setEnabled: YES]; + [fFileField setEnabled: YES]; + [fRipBrowseButton setEnabled: YES]; + [fRipButton setEnabled: YES]; + [fRipButton setTitle: @"Rip"]; + [fSuspendButton setEnabled: NO]; + [fSuspendButton setTitle: @"Suspend"]; + + if( status.fMode == HB_MODE_DONE ) + { + [fRipStatusField setStringValue: @"Done." ]; + [fRipProgress setDoubleValue: 100]; + NSBeep(); + [NSApp requestUserAttention: NSInformationalRequest]; + [NSApp beginSheet: fDonePanel + modalForWindow: fWindow + modalDelegate: nil + didEndSelector: nil + contextInfo: nil]; + [NSApp runModalForWindow: fDonePanel]; + [NSApp endSheet: fDonePanel]; + [fDonePanel orderOut: self]; + } + else if( status.fMode == HB_MODE_CANCELED ) + { + [fRipStatusField setStringValue: @"Canceled." ]; + [fRipProgress setDoubleValue: 0]; + } + else + { + [fRipStatusField setStringValue: @"An error occured." ]; + [fRipProgress setDoubleValue: 0]; + } + + /* Warn the finder to update itself */ + [[NSWorkspace sharedWorkspace] noteFileSystemChanged: + [fFileField stringValue]]; + break; + + default: + break; + } + } + + /* Do it again 1/10 second later */ + [NSTimer scheduledTimerWithTimeInterval: 0.1 + target: self selector: @selector( UpdateIntf: ) + userInfo: nil repeats: FALSE]; +} + +- (void) DetectDrives +{ + /* Empty the current popup */ + [fDVDPopUp removeAllItems]; + + /* Scan DVD drives (stolen from VLC) */ + io_object_t next_media; + mach_port_t master_port; + kern_return_t kern_result; + io_iterator_t media_iterator; + CFMutableDictionaryRef classes_to_match; + + kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); + if( kern_result != KERN_SUCCESS ) + { + return; + } + + classes_to_match = IOServiceMatching( kIODVDMediaClass ); + if( classes_to_match == NULL ) + { + return; + } + + CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectable ), + kCFBooleanTrue ); + + kern_result = + IOServiceGetMatchingServices( master_port, classes_to_match, + &media_iterator ); + if( kern_result != KERN_SUCCESS ) + { + return; + } + + next_media = IOIteratorNext( media_iterator ); + if( next_media != NULL ) + { + char psz_buf[0x32]; + size_t dev_path_length; + CFTypeRef str_bsd_path; + do + { + str_bsd_path = + IORegistryEntryCreateCFProperty( next_media, + CFSTR( kIOBSDName ), + kCFAllocatorDefault, + 0 ); + if( str_bsd_path == NULL ) + { + IOObjectRelease( next_media ); + continue; + } + + snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' ); + dev_path_length = strlen( psz_buf ); + + if( CFStringGetCString( (CFStringRef) str_bsd_path, + (char*)&psz_buf + dev_path_length, + sizeof(psz_buf) - dev_path_length, + kCFStringEncodingASCII ) ) + { + [[fDVDPopUp menu] addItemWithTitle: + [NSString stringWithCString: psz_buf] + action: nil keyEquivalent: @""]; + } + + CFRelease( str_bsd_path ); + + IOObjectRelease( next_media ); + + } while( ( next_media = IOIteratorNext( media_iterator ) ) != NULL ); + } + + IOObjectRelease( media_iterator ); +} + +- (void) ScanEnableIntf: (id) sender +{ + if( ![fScanMatrix selectedRow] ) + { + [fDVDPopUp setEnabled: YES]; + [fDVDFolderField setEnabled: NO]; + [fScanBrowseButton setEnabled: NO]; + [fScanButton setEnabled: ( [fDVDPopUp selectedItem] != nil )]; + } + else + { + [fDVDPopUp setEnabled: NO]; + [fDVDFolderField setEnabled: YES]; + [fScanBrowseButton setEnabled: YES]; + [fScanButton setEnabled: YES]; + } +} + +- (void) UpdatePopUp: (id) sender +{ + HBTitle * title = (HBTitle*) + fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); + + [fAudioPopUp removeAllItems]; + + HBAudio * audio; + for( uint32_t i = 0; i < title->fAudioList->CountItems(); i++ ) + { + audio = (HBAudio*) title->fAudioList->ItemAt( i ); + + /* We cannot use NSPopUpButton's addItemWithTitle because + it checks for duplicate entries */ + [[fAudioPopUp menu] addItemWithTitle: + [NSString stringWithCString: audio->fDescription] + action: nil keyEquivalent: @""]; + } +} + +@end diff --git a/macosx/HandBrake.icns b/macosx/HandBrake.icns Binary files differnew file mode 100644 index 000000000..f1d08d36f --- /dev/null +++ b/macosx/HandBrake.icns diff --git a/macosx/HandBrake.pbproj/project.pbxproj b/macosx/HandBrake.pbproj/project.pbxproj new file mode 100644 index 000000000..b4ea5fef5 --- /dev/null +++ b/macosx/HandBrake.pbproj/project.pbxproj @@ -0,0 +1,577 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 38; + objects = { + 080E96DCFE201CFB7F000001 = { + fileRef = 29B97318FDCFA39411CA2CEA; + isa = PBXBuildFile; + settings = { + }; + }; + 080E96DDFE201D6D7F000001 = { + children = ( + 4DF3C8CB052889CD00A80101, + 4DF3C8CC052889CD00A80101, + 4D85758E052B78E300C39CA9, + 4D85758F052B78E300C39CA9, + ); + isa = PBXGroup; + name = Classes; + refType = 4; + }; + 089C165CFE840E0CC02AAC07 = { + children = ( + 089C165DFE840E0CC02AAC07, + ); + isa = PBXVariantGroup; + name = InfoPlist.strings; + refType = 4; + }; + 089C165DFE840E0CC02AAC07 = { + fileEncoding = 10; + isa = PBXFileReference; + name = English; + path = English.lproj/InfoPlist.strings; + refType = 4; + }; + 089C165EFE840E0CC02AAC07 = { + fileRef = 089C165CFE840E0CC02AAC07; + isa = PBXBuildFile; + settings = { + }; + }; +//080 +//081 +//082 +//083 +//084 +//100 +//101 +//102 +//103 +//104 + 1058C7A0FEA54F0111CA2CBB = { + children = ( + 1058C7A1FEA54F0111CA2CBB, + 4DEB2024052B055F00C39CA9, + 4DDE9724052B7B2B00C39CA9, + ); + isa = PBXGroup; + name = "Linked Frameworks"; + refType = 4; + }; + 1058C7A1FEA54F0111CA2CBB = { + isa = PBXFrameworkReference; + name = Cocoa.framework; + path = /System/Library/Frameworks/Cocoa.framework; + refType = 0; + }; + 1058C7A2FEA54F0111CA2CBB = { + children = ( + 29B97325FDCFA39411CA2CEA, + 29B97324FDCFA39411CA2CEA, + ); + isa = PBXGroup; + name = "Other Frameworks"; + refType = 4; + }; + 1058C7A3FEA54F0111CA2CBB = { + fileRef = 1058C7A1FEA54F0111CA2CBB; + isa = PBXBuildFile; + settings = { + }; + }; +//100 +//101 +//102 +//103 +//104 +//170 +//171 +//172 +//173 +//174 + 17587328FF379C6511CA2CBB = { + isa = PBXApplicationReference; + path = HandBrake.app; + refType = 3; + }; +//170 +//171 +//172 +//173 +//174 +//190 +//191 +//192 +//193 +//194 + 19C28FACFE9D520D11CA2CBB = { + children = ( + 17587328FF379C6511CA2CBB, + ); + isa = PBXGroup; + name = Products; + refType = 4; + }; +//190 +//191 +//192 +//193 +//194 +//290 +//291 +//292 +//293 +//294 + 29B97313FDCFA39411CA2CEA = { + buildStyles = ( + 4A9504CCFFE6A4B311CA0CBA, + 4A9504CDFFE6A4B311CA0CBA, + ); + hasScannedForEncodings = 1; + isa = PBXProject; + mainGroup = 29B97314FDCFA39411CA2CEA; + projectDirPath = ""; + targets = ( + 29B97326FDCFA39411CA2CEA, + ); + }; + 29B97314FDCFA39411CA2CEA = { + children = ( + 080E96DDFE201D6D7F000001, + 29B97315FDCFA39411CA2CEA, + 29B97317FDCFA39411CA2CEA, + 29B97323FDCFA39411CA2CEA, + 19C28FACFE9D520D11CA2CBB, + ); + isa = PBXGroup; + name = HandBrake; + path = ""; + refType = 4; + }; + 29B97315FDCFA39411CA2CEA = { + children = ( + 29B97316FDCFA39411CA2CEA, + 4D929FEB0527903D00A80101, + ); + isa = PBXGroup; + name = "Other Sources"; + path = ""; + refType = 4; + }; + 29B97316FDCFA39411CA2CEA = { + fileEncoding = 30; + isa = PBXFileReference; + path = main.mm; + refType = 4; + }; + 29B97317FDCFA39411CA2CEA = { + children = ( + 29B97318FDCFA39411CA2CEA, + 4D929FED0527907200A80101, + 4D69F5C80527944A00A80101, + 4D69F5C90527944A00A80101, + 4D69F5CA0527944A00A80101, + 4D69F5CB0527944A00A80101, + 4D69F5CC0527944A00A80101, + 4D69F5CD0527944A00A80101, + 4D69F5CE0527944A00A80101, + 4D118405053054CD00C39CA9, + 089C165CFE840E0CC02AAC07, + ); + isa = PBXGroup; + name = Resources; + path = ""; + refType = 4; + }; + 29B97318FDCFA39411CA2CEA = { + children = ( + 29B97319FDCFA39411CA2CEA, + ); + isa = PBXVariantGroup; + name = MainMenu.nib; + path = ""; + refType = 4; + }; + 29B97319FDCFA39411CA2CEA = { + isa = PBXFileReference; + name = English; + path = English.lproj/MainMenu.nib; + refType = 4; + }; + 29B97323FDCFA39411CA2CEA = { + children = ( + 1058C7A0FEA54F0111CA2CBB, + 1058C7A2FEA54F0111CA2CBB, + ); + isa = PBXGroup; + name = Frameworks; + path = ""; + refType = 4; + }; + 29B97324FDCFA39411CA2CEA = { + isa = PBXFrameworkReference; + name = AppKit.framework; + path = /System/Library/Frameworks/AppKit.framework; + refType = 0; + }; + 29B97325FDCFA39411CA2CEA = { + isa = PBXFrameworkReference; + name = Foundation.framework; + path = /System/Library/Frameworks/Foundation.framework; + refType = 0; + }; + 29B97326FDCFA39411CA2CEA = { + buildPhases = ( + 29B97327FDCFA39411CA2CEA, + 29B97328FDCFA39411CA2CEA, + 29B9732BFDCFA39411CA2CEA, + 29B9732DFDCFA39411CA2CEA, + ); + buildSettings = { + FRAMEWORK_SEARCH_PATHS = ""; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + HEADER_SEARCH_PATHS = ""; + LIBRARY_SEARCH_PATHS = ../core; + OPTIMIZATION_CFLAGS = "-O3"; + OTHER_CFLAGS = "-DSYS_MACOSX"; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = HandBrake; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + WRAPPER_EXTENSION = app; + }; + dependencies = ( + ); + isa = PBXApplicationTarget; + name = HandBrake; + productName = HandBrake; + productReference = 17587328FF379C6511CA2CBB; + productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> +<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> +<plist version=\"1.0\"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>HandBrake</string> + <key>CFBundleGetInfoString</key> + <string>HandBrake 0.3 - By Eric Petit <[email protected]></string> + <key>CFBundleIconFile</key> + <string>HandBrake.icns</string> + <key>CFBundleIdentifier</key> + <string>org.m0k.handbrake</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>HandBrake</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>0.3</string> + <key>CFBundleSignature</key> + <string>HB##</string> + <key>CFBundleVersion</key> + <string>0.3</string> + <key>NSMainNibFile</key> + <string>MainMenu</string> + <key>NSPrincipalClass</key> + <string>NSApplication</string> +</dict> +</plist> +"; + }; + 29B97327FDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + 4D929FEC0527903D00A80101, + 4D6615EA05288C2300A80101, + 4D857591052B78E300C39CA9, + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 29B97328FDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + 080E96DCFE201CFB7F000001, + 089C165EFE840E0CC02AAC07, + 4D118406053054CD00C39CA9, + ); + isa = PBXResourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 29B9732BFDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + 29B9732CFDCFA39411CA2CEA, + 4DF3C8CE052889CD00A80101, + 4D857590052B78E300C39CA9, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + 29B9732CFDCFA39411CA2CEA = { + fileRef = 29B97316FDCFA39411CA2CEA; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + 29B9732DFDCFA39411CA2CEA = { + buildActionMask = 2147483647; + files = ( + 1058C7A3FEA54F0111CA2CBB, + 4D929FEE0527907200A80101, + 4D69F5CF0527944A00A80101, + 4D69F5D00527944A00A80101, + 4D69F5D10527944A00A80101, + 4D69F5D20527944A00A80101, + 4D69F5D30527944A00A80101, + 4D69F5D40527944A00A80101, + 4D69F5D50527944A00A80101, + 4DEB2025052B055F00C39CA9, + 4DDE9725052B7B2B00C39CA9, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; +//290 +//291 +//292 +//293 +//294 +//4A0 +//4A1 +//4A2 +//4A3 +//4A4 + 4A9504CCFFE6A4B311CA0CBA = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = NO; + OPTIMIZATION_CFLAGS = "-O0"; + }; + isa = PBXBuildStyle; + name = Development; + }; + 4A9504CDFFE6A4B311CA0CBA = { + buildRules = ( + ); + buildSettings = { + COPY_PHASE_STRIP = YES; + }; + isa = PBXBuildStyle; + name = Deployment; + }; +//4A0 +//4A1 +//4A2 +//4A3 +//4A4 +//4D0 +//4D1 +//4D2 +//4D3 +//4D4 + 4D118405053054CD00C39CA9 = { + isa = PBXFileReference; + path = HandBrake.icns; + refType = 4; + }; + 4D118406053054CD00C39CA9 = { + fileRef = 4D118405053054CD00C39CA9; + isa = PBXBuildFile; + settings = { + }; + }; + 4D6615EA05288C2300A80101 = { + fileRef = 4DF3C8CB052889CD00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D69F5C80527944A00A80101 = { + isa = PBXFileReference; + name = liba52.a; + path = /usr/local/lib/liba52.a; + refType = 0; + }; + 4D69F5C90527944A00A80101 = { + isa = PBXFileReference; + name = libavcodec.a; + path = /usr/local/lib/libavcodec.a; + refType = 0; + }; + 4D69F5CA0527944A00A80101 = { + isa = PBXFileReference; + name = libdvdcss.a; + path = /usr/local/lib/libdvdcss.a; + refType = 0; + }; + 4D69F5CB0527944A00A80101 = { + isa = PBXFileReference; + name = libdvdplay.a; + path = /usr/local/lib/libdvdplay.a; + refType = 0; + }; + 4D69F5CC0527944A00A80101 = { + isa = PBXFileReference; + name = libdvdread.a; + path = /usr/local/lib/libdvdread.a; + refType = 0; + }; + 4D69F5CD0527944A00A80101 = { + isa = PBXFileReference; + name = libmp3lame.a; + path = /usr/local/lib/libmp3lame.a; + refType = 0; + }; + 4D69F5CE0527944A00A80101 = { + isa = PBXFileReference; + name = libmpeg2.a; + path = /usr/local/lib/libmpeg2.a; + refType = 0; + }; + 4D69F5CF0527944A00A80101 = { + fileRef = 4D69F5C80527944A00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D69F5D00527944A00A80101 = { + fileRef = 4D69F5C90527944A00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D69F5D10527944A00A80101 = { + fileRef = 4D69F5CA0527944A00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D69F5D20527944A00A80101 = { + fileRef = 4D69F5CB0527944A00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D69F5D30527944A00A80101 = { + fileRef = 4D69F5CC0527944A00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D69F5D40527944A00A80101 = { + fileRef = 4D69F5CD0527944A00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D69F5D50527944A00A80101 = { + fileRef = 4D69F5CE0527944A00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D85758E052B78E300C39CA9 = { + fileEncoding = 30; + isa = PBXFileReference; + path = PictureGLView.mm; + refType = 4; + }; + 4D85758F052B78E300C39CA9 = { + fileEncoding = 30; + isa = PBXFileReference; + path = PictureGLView.h; + refType = 4; + }; + 4D857590052B78E300C39CA9 = { + fileRef = 4D85758E052B78E300C39CA9; + isa = PBXBuildFile; + settings = { + }; + }; + 4D857591052B78E300C39CA9 = { + fileRef = 4D85758F052B78E300C39CA9; + isa = PBXBuildFile; + settings = { + }; + }; + 4D929FEB0527903D00A80101 = { + fileEncoding = 30; + isa = PBXFileReference; + name = Manager.h; + path = ../core/Manager.h; + refType = 4; + }; + 4D929FEC0527903D00A80101 = { + fileRef = 4D929FEB0527903D00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4D929FED0527907200A80101 = { + isa = PBXFileReference; + name = libhb.a; + path = ../core/libhb.a; + refType = 4; + }; + 4D929FEE0527907200A80101 = { + fileRef = 4D929FED0527907200A80101; + isa = PBXBuildFile; + settings = { + }; + }; + 4DDE9724052B7B2B00C39CA9 = { + isa = PBXFrameworkReference; + name = OpenGL.framework; + path = /System/Library/Frameworks/OpenGL.framework; + refType = 0; + }; + 4DDE9725052B7B2B00C39CA9 = { + fileRef = 4DDE9724052B7B2B00C39CA9; + isa = PBXBuildFile; + settings = { + }; + }; + 4DEB2024052B055F00C39CA9 = { + isa = PBXFrameworkReference; + name = IOKit.framework; + path = /System/Library/Frameworks/IOKit.framework; + refType = 0; + }; + 4DEB2025052B055F00C39CA9 = { + fileRef = 4DEB2024052B055F00C39CA9; + isa = PBXBuildFile; + settings = { + }; + }; + 4DF3C8CB052889CD00A80101 = { + fileEncoding = 30; + isa = PBXFileReference; + path = HBController.h; + refType = 4; + }; + 4DF3C8CC052889CD00A80101 = { + fileEncoding = 30; + isa = PBXFileReference; + path = HBController.mm; + refType = 4; + }; + 4DF3C8CE052889CD00A80101 = { + fileRef = 4DF3C8CC052889CD00A80101; + isa = PBXBuildFile; + settings = { + }; + }; + }; + rootObject = 29B97313FDCFA39411CA2CEA; +} diff --git a/macosx/PictureGLView.h b/macosx/PictureGLView.h new file mode 100644 index 000000000..effbf3ee2 --- /dev/null +++ b/macosx/PictureGLView.h @@ -0,0 +1,20 @@ +/* PictureGLView */ + +#include <Cocoa/Cocoa.h> + +#include "Manager.h" + +@interface PictureGLView : NSOpenGLView + +{ + HBManager * fManager; + HBTitle * fTitle; + + uint8_t * fPicture; +} + +- (void) SetManager: (HBManager*) manager; +- (void) SetTitle: (HBTitle*) title; +- (void) ShowPicture: (int) picture; + +@end diff --git a/macosx/PictureGLView.mm b/macosx/PictureGLView.mm new file mode 100644 index 000000000..72e564141 --- /dev/null +++ b/macosx/PictureGLView.mm @@ -0,0 +1,114 @@ +#include <OpenGL/gl.h> + +#include "PictureGLView.h" + +@implementation PictureGLView + +- (void) SetManager: (HBManager*) manager +{ + fManager = manager; +} + +- (void) SetTitle: (HBTitle*) title +{ + fTitle = title; + + /* This is needed as the view's size may have changed */ + [self clearGLContext]; + [self openGLContext]; +} + +- (void) ShowPicture: (int) index +{ + /* Get the picture */ + uint8_t * tmp = fManager->GetPreview( fTitle, index ); + + /* Make it be upside-down */ + if( fPicture ) free( fPicture ); + fPicture = (uint8_t*) malloc( 4 * ( fTitle->fOutWidthMax + 2 ) * + ( fTitle->fOutHeightMax + 2 ) ); + for( uint32_t i = 0; i < fTitle->fOutHeightMax + 2; i++ ) + { + memcpy( fPicture + 4 * ( fTitle->fOutWidthMax + 2 ) * i, + tmp + 4 * ( fTitle->fOutWidthMax + 2 ) * + ( fTitle->fOutHeightMax + 1 - i ), + 4 * ( fTitle->fOutWidthMax + 2 ) ); + } + free( tmp ); + + /* Grrr - should find a way to give ARGB to OpenGL */ + uint8_t r, g, b, a; + for( uint32_t i = 0; i < fTitle->fOutHeightMax + 2; i++ ) + { + for( uint32_t j = 0; j < fTitle->fOutWidthMax + 2; j++ ) + { + a = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)]; + r = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+1]; + g = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+2]; + b = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+3]; + + fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)] = r; + fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+1] = g; + fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+2] = b; + fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+3] = a; + } + } + + [self setNeedsDisplay: YES]; +} + +/* Override NSView's initWithFrame: to specify our pixel format */ +- (id) initWithFrame: (NSRect) frame +{ + fManager = NULL; + fTitle = NULL; + fPicture = NULL; + + GLuint attribs[] = + { + NSOpenGLPFANoRecovery, + NSOpenGLPFAWindow, + NSOpenGLPFAAccelerated, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFAStencilSize, 8, + NSOpenGLPFAAccumSize, 0, + 0 + }; + + NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] + initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs]; + + if( !fmt ) + { + fprintf( stderr, "Sarass\n" ); + } + + return self = [super initWithFrame:frame pixelFormat: + [fmt autorelease]]; +} + +/* Override the view's drawRect: to draw our GL content */ +- (void) drawRect: (NSRect) rect +{ + glViewport( 0, 0, (GLsizei) rect.size.width, + (GLsizei) rect.size.height ); + + /* Black background */ + glClearColor( 0, 0, 0, 0 ); + glClear( GL_COLOR_BUFFER_BIT ); + + /* Show it */ + if( fPicture ) + { + glDrawPixels( fTitle->fOutWidthMax + 2, + fTitle->fOutHeightMax + 2, GL_RGBA, + GL_UNSIGNED_BYTE, fPicture ); + } + + [[self openGLContext] flushBuffer]; +} + +@end diff --git a/macosx/main.mm b/macosx/main.mm new file mode 100644 index 000000000..56aa102fa --- /dev/null +++ b/macosx/main.mm @@ -0,0 +1,12 @@ +/* $Id: main.mm,v 1.5 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. */ + +#import <Cocoa/Cocoa.h> + +int main( int argc, const char ** argv ) +{ + return NSApplicationMain( argc, argv ); +} diff --git a/test/Test.cpp b/test/Test.cpp new file mode 100644 index 000000000..d0d5ec9ea --- /dev/null +++ b/test/Test.cpp @@ -0,0 +1,229 @@ +/* $Id: Test.cpp,v 1.5 2003/10/05 14:28:40 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 <signal.h> + +#include "Manager.h" + +volatile bool die; + +void SigHandler( int signal ) +{ + die = true; +} + +int main( int argc, char ** argv ) +{ + die = false; + + /* Exit ASAP on Ctrl-C */ + signal( SIGINT, SigHandler ); + + /* Default values */ + bool debug = false; + char * device = NULL; + char * outputFile = NULL; + int titleIdx = 1; + bool twoPass = false; + bool deinterlace = false; + int width = 0; + int topCrop = 0; + int bottomCrop = 0; + int leftCrop = 0; + int rightCrop = 0; + + /* Parse command line */ + int c; + while( ( c = getopt( argc, argv, "vd:o:t:piw:j:k:l:m:" ) ) != -1 ) + { + switch( c ) + { + case 'v': + debug = true; + break; + + case 'd': + device = strdup( optarg ); + break; + + case 'o': + outputFile = strdup( optarg ); + break; + + case 't': + titleIdx = atoi( optarg ); + break; + + case 'p': + twoPass = true; + break; + + case 'i': + deinterlace = true; + break; + + case 'w': + width = atoi( optarg ); + break; + + case 'j': + topCrop = atoi( optarg ); + break; + + case 'k': + bottomCrop = atoi( optarg ); + break; + + case 'l': + leftCrop = atoi( optarg ); + break; + + case 'm': + rightCrop = atoi( optarg ); + break; + + default: + break; + } + } + + /* Check parsed options */ + if( !device || !outputFile ) + { + fprintf( stderr, + "Syntax: HBTest [options] -d <device> -o <file>\n" + "Possible options are :\n" + " -v verbose output\n" + " -t <value> select a title (default is 1)\n" + " -p 2-pass encoding\n" + " -i deinterlace picture\n" + " -w output width\n" + " -j <value> top cropping\n" + " -k <value> bottom cropping\n" + " -l <value> left cropping\n" + " -m <value> right cropping\n" ); + return 1; + } + + /* Create the manager thread */ + HBManager * manager = new HBManager( debug ); + + /* Tell the manager to scan the specified volume */ + manager->ScanVolumes( device ); + + HBStatus status; + while( !die ) + { + if( !manager->NeedUpdate() ) + { + Snooze( 10000 ); + continue; + } + + status = manager->GetStatus(); + + switch( status.fMode ) + { + case HB_MODE_UNDEF: + break; + + case HB_MODE_SCANNING: + if( !status.fScannedTitle ) + { + fprintf( stderr, "Scanning %s\n", + status.fScannedVolume ); + } + else + { + fprintf( stderr, "Scanning %s, title %d\n", + status.fScannedVolume, + status.fScannedTitle ); + } + break; + + case HB_MODE_READY_TO_RIP: + { + /* Find the title */ + HBTitle * title = NULL; + for( uint32_t i = 0; i < status.fTitleList->CountItems(); i++ ) + { + title = (HBTitle*) status.fTitleList->ItemAt( i ); + if( title->fIndex == titleIdx ) + { + break; + } + else + { + title = NULL; + } + } + + if( !title ) + { + fprintf( stderr, "Error: unvalid title. Possible " + "choices are: " ); + for( uint32_t i = 0; + i < status.fTitleList->CountItems(); i++ ) + { + title = (HBTitle*) status.fTitleList->ItemAt( i ); + fprintf( stderr, "%d%s", title->fIndex, + ( i == status.fTitleList->CountItems() - 1 ) + ? ".\n" : ", " ); + } + die = true; + break; + } + title->fTwoPass = twoPass; + title->fDeinterlace = deinterlace; + if( width ) title->fOutWidth = width; + title->fTopCrop = topCrop; + title->fBottomCrop = bottomCrop; + title->fLeftCrop = leftCrop; + title->fRightCrop = rightCrop; + + HBAudio * audio = (HBAudio*) title->fAudioList->ItemAt( 0 ); + + manager->StartRip( title, audio, NULL, outputFile ); + break; + } + + case HB_MODE_ENCODING: + fprintf( stderr, "Progress = %.2f %%, %.2f fps " + "(%02d:%02d:%02d remaining)\n", + 100 * status.fPosition, status.fFrameRate, + status.fRemainingTime / 3600, + ( status.fRemainingTime % 3600 ) / 60, + status.fRemainingTime % 60 ); + break; + + case HB_MODE_DONE: + fprintf( stderr, "Done\n" ); + die = true; + break; + + case HB_MODE_CANCELED: + fprintf( stderr, "Canceled\n" ); + die = true; + break; + + case HB_MODE_ERROR: + fprintf( stderr, "Error\n" ); + die = true; + break; + + default: + break; + } + } + + delete manager; + + if( device ) free( device ); + if( outputFile ) free( outputFile ); + + return 0; +} + |