summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhandbrake <[email protected]>2006-01-14 12:53:59 +0000
committerhandbrake <[email protected]>2006-01-14 12:53:59 +0000
commita9a84221af31ca7d11d1aa182d8b152270203f9f (patch)
treeda452de9a4d3bb509d59de4a65fe12e9fb8e7825
parent939b35fc70bb688d38b086afebd8d14d8193d2c9 (diff)
HandBrake 0.3
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@4 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r--CREDITS29
-rw-r--r--HBAc3Decoder.h29
-rw-r--r--HBApp.cpp68
-rw-r--r--HBApp.h23
-rw-r--r--HBAviMuxer.cpp338
-rw-r--r--HBAviMuxer.h149
-rw-r--r--HBCommon.cpp567
-rw-r--r--HBCommon.h146
-rw-r--r--HBDVDReader.cpp67
-rw-r--r--HBDVDReader.h23
-rw-r--r--HBFifo.cpp161
-rw-r--r--HBFifo.h61
-rw-r--r--HBManager.cpp319
-rw-r--r--HBManager.h55
-rw-r--r--HBMp3Encoder.h30
-rw-r--r--HBMpeg2Decoder.cpp168
-rw-r--r--HBMpeg2Decoder.h27
-rw-r--r--HBMpeg4Encoder.cpp88
-rw-r--r--HBMpeg4Encoder.h27
-rw-r--r--HBMpegDemux.h38
-rw-r--r--HBPictureWin.cpp290
-rw-r--r--HBThread.cpp49
-rw-r--r--HBThread.h26
-rw-r--r--HBWindow.cpp633
-rw-r--r--HBWindow.h62
-rw-r--r--HandBrake.cpp18
-rw-r--r--Jamfile94
-rw-r--r--NEWS12
-rw-r--r--TODO10
-rw-r--r--beos/HandBrake.cpp52
-rw-r--r--beos/HandBrake.h22
-rw-r--r--beos/MainWindow.cpp759
-rw-r--r--beos/MainWindow.h100
-rw-r--r--beos/PictureWin.cpp233
-rw-r--r--beos/PictureWin.h (renamed from HBPictureWin.h)31
-rw-r--r--core/Ac3Decoder.cpp (renamed from HBAc3Decoder.cpp)87
-rw-r--r--core/Ac3Decoder.h33
-rw-r--r--core/AviMuxer.cpp479
-rw-r--r--core/AviMuxer.h153
-rw-r--r--core/Common.cpp220
-rw-r--r--core/Common.h192
-rw-r--r--core/DVDReader.cpp96
-rw-r--r--core/DVDReader.h25
-rw-r--r--core/Fifo.cpp119
-rw-r--r--core/Fifo.h49
-rw-r--r--core/Languages.h184
-rw-r--r--core/Manager.cpp707
-rw-r--r--core/Manager.h61
-rw-r--r--core/Mp3Encoder.cpp (renamed from HBMp3Encoder.cpp)88
-rw-r--r--core/Mp3Encoder.h34
-rw-r--r--core/Mpeg2Decoder.cpp137
-rw-r--r--core/Mpeg2Decoder.h34
-rw-r--r--core/Mpeg4Encoder.cpp150
-rw-r--r--core/Mpeg4Encoder.h36
-rw-r--r--core/MpegDemux.cpp (renamed from HBMpegDemux.cpp)152
-rw-r--r--core/MpegDemux.h40
-rw-r--r--core/Resizer.cpp89
-rw-r--r--core/Resizer.h25
-rw-r--r--core/Scanner.cpp275
-rw-r--r--core/Scanner.h27
-rw-r--r--core/Thread.cpp171
-rw-r--r--core/Thread.h76
-rw-r--r--macosx/English.lproj/InfoPlist.stringsbin0 -> 488 bytes
-rw-r--r--macosx/English.lproj/MainMenu.nib/classes.nib70
-rw-r--r--macosx/English.lproj/MainMenu.nib/info.nib29
-rw-r--r--macosx/English.lproj/MainMenu.nib/objects.nibbin0 -> 14905 bytes
-rw-r--r--macosx/HBController.h88
-rw-r--r--macosx/HBController.mm627
-rw-r--r--macosx/HandBrake.icnsbin0 -> 64031 bytes
-rw-r--r--macosx/HandBrake.pbproj/project.pbxproj577
-rw-r--r--macosx/PictureGLView.h20
-rw-r--r--macosx/PictureGLView.mm114
-rw-r--r--macosx/main.mm12
-rw-r--r--test/Test.cpp229
74 files changed, 6669 insertions, 3640 deletions
diff --git a/CREDITS b/CREDITS
index b8dee5f5b..110e1cc02 100644
--- a/CREDITS
+++ b/CREDITS
@@ -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;
-}
diff --git a/Jamfile b/Jamfile
index aa84b1ea4..31e4874a2 100644
--- a/Jamfile
+++ b/Jamfile
@@ -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 ;
diff --git a/NEWS b/NEWS
index 75542b955..9160a5509 100644
--- a/NEWS
+++ b/NEWS
@@ -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.
diff --git a/TODO b/TODO
new file mode 100644
index 000000000..fcbbe2a5e
--- /dev/null
+++ b/TODO
@@ -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( &param, 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, &param ) )
+ {
+ 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
new file mode 100644
index 000000000..ae4f04858
--- /dev/null
+++ b/macosx/English.lproj/InfoPlist.strings
Binary files differ
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
new file mode 100644
index 000000000..a7849eb54
--- /dev/null
+++ b/macosx/English.lproj/MainMenu.nib/objects.nib
Binary files differ
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
new file mode 100644
index 000000000..f1d08d36f
--- /dev/null
+++ b/macosx/HandBrake.icns
Binary files differ
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 &lt;[email protected]&gt;</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;
+}
+