diff options
author | handbrake <[email protected]> | 2006-01-14 12:56:59 +0000 |
---|---|---|
committer | handbrake <[email protected]> | 2006-01-14 12:56:59 +0000 |
commit | 452f36599a1ea52f3bd42361b534594568c428fd (patch) | |
tree | 7f53f79212cf524f0a13ed5ee2250992f21eabcb | |
parent | a9a84221af31ca7d11d1aa182d8b152270203f9f (diff) |
HandBrake 0.4
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@5 b64f7644-9d1e-0410-96f1-a4d463321fa5
48 files changed, 2921 insertions, 1619 deletions
@@ -1,10 +1,10 @@ -# $Id: Jamfile,v 1.33 2003/10/06 21:21:27 titer Exp $ +# $Id: Jamfile,v 1.38 2003/10/13 23:46:41 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.3 ; +HB_VERSION = 0.4 ; # Compilers C++ = g++ ; @@ -28,7 +28,7 @@ LINKLIBS = -ldvdplay -ldvdread -ldvdcss -lmpeg2 -lavcodec -la52 -lmp3lame ; if $(OS) = BEOS { C++FLAGS += -Wno-multichar ; - LINKLIBS += -lbe ; + LINKLIBS += -lbe -ltracker ; } else if $(OS) = LINUX { @@ -65,7 +65,7 @@ Library core/libhb : core/Ac3Decoder.cpp core/AviMuxer.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 ; + core/Scanner.cpp core/Thread.cpp core/Worker.cpp ; LinkLibraries HBTest : core/libhb.a ; Main HBTest : test/Test.cpp ; @@ -74,7 +74,8 @@ if $(OS) = BEOS { LinkLibraries HandBrake : core/libhb.a ; Main HandBrake : beos/HandBrake.cpp beos/MainWindow.cpp - beos/PictureWin.cpp ; + beos/PictureWin.cpp beos/ScanView.cpp + beos/RipView.cpp ; } if $(OS) = MACOSX @@ -1,4 +1,10 @@ -$Id: NEWS,v 1.9 2003/10/06 21:21:27 titer Exp $ +$Id: NEWS,v 1.11 2003/10/13 15:35:38 titer Exp $ + +Changes between 0.3 and 0.4 + - Better multithreading + - Allow the user to specify a target size instead of bitrate + - Misc GUI enhancements + - Use low-priority threads on OS X Changes between 0.2 and 0.3 - OSX & Linux ports @@ -1,10 +1,8 @@ - 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 + + Should be able to boost the audio volume - OSX port - + Check thread priorities - + "Ding" when done + window + "Ahuh" + Preview in a drawer + + Prompt before overwriting a file diff --git a/beos/HandBrake.cpp b/beos/HandBrake.cpp index b1b386a6d..b5f13196b 100644 --- a/beos/HandBrake.cpp +++ b/beos/HandBrake.cpp @@ -1,4 +1,4 @@ -/* $Id: HandBrake.cpp,v 1.6 2003/09/30 14:38:15 titer Exp $ +/* $Id: HandBrake.cpp,v 1.8 2003/10/13 22:23:02 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -11,42 +11,47 @@ void SigHandler( int signal ) { + /* Ugly way to exit cleanly when hitting Ctrl-C */ ((HBApp*) be_app)->fWindow->PostMessage( B_QUIT_REQUESTED ); } -int main( int argc, char ** argv ) +int main() { 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 ); + HBApp * app = new HBApp(); app->Run(); delete app; return 0; } /* Constructor */ -HBApp::HBApp( bool debug ) - : BApplication( "application/x-vnd.titer-handbrake" ) +HBApp::HBApp() + : BApplication("application/x-vnd.titer-handbrake" ) { - fWindow = new HBWindow( debug ); + fWindow = new MainWindow(); fWindow->Show(); } +void HBApp::MessageReceived( BMessage * message ) +{ + switch( message->what ) + { + case B_SAVE_REQUESTED: + fWindow->PostMessage( message ); + break; + + default: + BApplication::MessageReceived( message ); + break; + } +} + +void HBApp::RefsReceived( BMessage * message ) +{ + fWindow->PostMessage( message ); +} + diff --git a/beos/HandBrake.h b/beos/HandBrake.h index 72234e195..7035b5487 100644 --- a/beos/HandBrake.h +++ b/beos/HandBrake.h @@ -1,4 +1,4 @@ -/* $Id: HandBrake.h,v 1.5 2003/09/30 14:38:15 titer Exp $ +/* $Id: HandBrake.h,v 1.7 2003/10/13 22:23:02 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -9,14 +9,16 @@ #include <Application.h> -class HBWindow; +class MainWindow; class HBApp : public BApplication { public: - HBApp( bool debug ); + HBApp(); + void MessageReceived( BMessage * message ); + void RefsReceived( BMessage * message ); - HBWindow * fWindow; + MainWindow * fWindow; }; #endif diff --git a/beos/HandBrake.rsrc b/beos/HandBrake.rsrc Binary files differnew file mode 100644 index 000000000..d9f87ee44 --- /dev/null +++ b/beos/HandBrake.rsrc diff --git a/beos/MainWindow.cpp b/beos/MainWindow.cpp index ca18537a5..613cf21df 100644 --- a/beos/MainWindow.cpp +++ b/beos/MainWindow.cpp @@ -1,248 +1,50 @@ -/* $Id: MainWindow.cpp,v 1.14 2003/10/05 14:56:38 titer Exp $ +/* $Id: MainWindow.cpp,v 1.19 2003/10/13 22:23:02 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" ); -} +#include "MainWindow.h" +#include "ScanView.h" +#include "RipView.h" -HBWindow::HBWindow( bool debug ) - : BWindow( WINDOW_RECT, "HandBrake " VERSION, B_TITLED_WINDOW, +MainWindow::MainWindow() + : BWindow( BRect( 0,0,10,10 ), "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 ); + fManager = new HBManager( true ); - /* Detects DVD drives & VOB folders, then tell libhb to scan it */ - ScanVolumes(); + /* Add the scan view */ + fScanView = new ScanView( fManager ); + fRipView = new RipView( fManager ); + AddChild( fScanView ); + + /* Resize to fit */ + ResizeTo( fScanView->Bounds().Width(), fScanView->Bounds().Height() ); + + BScreen screen; + MoveTo( ( screen.Frame().Width() - fRipView->Bounds().Width() ) / 2, + ( screen.Frame().Height() - fRipView->Bounds().Height() ) / 2 ); /* Update the interface */ + fDie = false; fUpdateThread = spawn_thread( (int32 (*)(void *)) UpdateInterface, "interface", B_DISPLAY_PRIORITY, this ); resume_thread( fUpdateThread ); } -bool HBWindow::QuitRequested() +bool MainWindow::QuitRequested() { /* Clean up */ - kill_thread( fUpdateThread ); + fDie = true; + long exit_value; + wait_for_thread( fUpdateThread, &exit_value ); delete fManager; /* Stop the application */ @@ -250,7 +52,7 @@ bool HBWindow::QuitRequested() return true; } -void HBWindow::MessageReceived( BMessage * message ) +void MainWindow::MessageReceived( BMessage * message ) { switch( message->what ) { @@ -269,209 +71,44 @@ void HBWindow::MessageReceived( BMessage * message ) 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(); + case B_REFS_RECEIVED: + case SCAN_RADIO: + case SCAN_BROWSE_BUTTON: + case SCAN_OPEN: + fScanView->MessageReceived( message ); 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() ); + case B_SAVE_REQUESTED: + case RIP_TITLE_POPUP: + case RIP_BITRATE_RADIO: + case RIP_TARGET_CONTROL: + case RIP_CROP_BUTTON: + case RIP_BROWSE_BUTTON: + case RIP_SUSPEND_BUTTON: + case RIP_RIP_BUTTON: + fRipView->MessageReceived( message ); 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() +void MainWindow::UpdateInterface( MainWindow * _this ) { - BVolumeRoster * roster = new BVolumeRoster(); - BVolume * bVolume = new BVolume(); - fs_info info; - int device; - device_geometry geometry; - - HBVolume * volume; - HBList * volumeList = new HBList(); + uint64_t time; - /* 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( ;; ) + while( !_this->fDie ) { + /* Update every 0.1 sec */ + time = system_time(); _this->_UpdateInterface(); - snooze( 10000 ); + snooze( 100000 - ( system_time() - time ) ); } } -void HBWindow::_UpdateInterface() +void MainWindow::_UpdateInterface() { if( !fManager->NeedUpdate() ) { @@ -486,97 +123,31 @@ void HBWindow::_UpdateInterface() return; } - EnableInterface( status.fMode ); - switch( status.fMode ) { case HB_MODE_UNDEF: + case HB_MODE_NEED_VOLUME: 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 ); + case HB_MODE_INVALID_VOLUME: + fScanView->UpdateIntf( status ); 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." ); + case HB_MODE_READY_TO_RIP: + RemoveChild( fScanView ); + ResizeTo( fRipView->Bounds().Width(), + fRipView->Bounds().Height() ); + AddChild( fRipView ); + fRipView->UpdateIntf( status ); 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: + fRipView->UpdateIntf( status ); break; default: @@ -586,174 +157,3 @@ void HBWindow::_UpdateInterface() 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 index e40c2587a..c4c32a711 100644 --- a/beos/MainWindow.h +++ b/beos/MainWindow.h @@ -1,4 +1,4 @@ -/* $Id: MainWindow.h,v 1.9 2003/09/30 14:38:15 titer Exp $ +/* $Id: MainWindow.h,v 1.10 2003/10/10 01:08:42 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,93 +8,29 @@ #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; +class ScanView; +class RipView; -/* libhb headers */ -#include "Manager.h" +#include "Common.h" -class HBVolumeItem : public BMenuItem +class MainWindow : public BWindow { 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 ); + MainWindow(); virtual bool QuitRequested(); virtual void MessageReceived( BMessage * message ); - void ScanVolumes(); - private: - static void UpdateInterface( HBWindow * _this ); + static void UpdateInterface( MainWindow * _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; + volatile bool fDie; - /* Used to SetEnabled() GUI items only if needed */ - HBMode fOldMode; + ScanView * fScanView; + RipView * fRipView; }; #endif diff --git a/beos/RipView.cpp b/beos/RipView.cpp new file mode 100644 index 000000000..180ba23ff --- /dev/null +++ b/beos/RipView.cpp @@ -0,0 +1,616 @@ +/* $Id: RipView.cpp,v 1.6 2003/10/13 23:42:03 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 <Box.h> +#include <Button.h> +#include <CheckBox.h> +#include <FilePanel.h> +#include <MenuField.h> +#include <MenuItem.h> +#include <Path.h> +#include <PopUpMenu.h> +#include <RadioButton.h> +#include <StatusBar.h> +#include <String.h> +#include <TextControl.h> + +#include "RipView.h" +#include "PictureWin.h" +#include "Manager.h" + +#define DEFAULT_FILE "/boot/home/Desktop/Movie.avi" + +RipView::RipView( HBManager * manager ) + : BView( BRect( 0,0,400,480 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW ) +{ + fManager = manager; + + BRect r; + SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); + + /* Video box */ + r = BRect( 10, 10, Bounds().Width() - 10, 160 ); + fVideoBox = new BBox( r ); + fVideoBox->SetLabel( "Video" ); + AddChild( fVideoBox ); + + /* Title */ + r = BRect( 10, 15, fVideoBox->Bounds().Width() - 10, 35 ); + fTitlePopUp = new BPopUpMenu( "" ); + fTitleField = new BMenuField( r, NULL, "Title:", + fTitlePopUp, true ); + fVideoBox->AddChild( fTitleField ); + + /* Video codec */ + r = BRect( 10, 40, fVideoBox->Bounds().Width() - 10, 60 ); + fVideoCodecPopUp = new BPopUpMenu( "" ); + fVideoCodecField = new BMenuField( r, NULL, "Codec:", + fVideoCodecPopUp, true ); + fVideoBox->AddChild( fVideoCodecField ); + + /* Video bitrate */ + r = BRect( 10, 65, fVideoBox->Bounds().Width() / 2, 85 ); + fCustomBitrateRadio = + new BRadioButton( r, NULL, "Custom bitrate (kbps)", + new BMessage( RIP_BITRATE_RADIO ) ); + fCustomBitrateRadio->SetValue( 1 ); + fVideoBox->AddChild( fCustomBitrateRadio ); + r = BRect( fVideoBox->Bounds().Width() - 80, 65, + fVideoBox->Bounds().Width() - 10, 85 ); + fCustomBitrateControl = new BTextControl( r, NULL, NULL, "1024", NULL ); + fCustomBitrateControl->SetDivider( 0 ); + fVideoBox->AddChild( fCustomBitrateControl ); + r = BRect( 10, 90, fVideoBox->Bounds().Width() / 2, 110 ); + fTargetSizeRadio = + new BRadioButton( r, NULL, "Target size (MB)", + new BMessage( RIP_BITRATE_RADIO ) ); + fVideoBox->AddChild( fTargetSizeRadio ); + r = BRect( fVideoBox->Bounds().Width() - 80, 90, + fVideoBox->Bounds().Width() - 10, 110 ); + fTargetSizeControl = new BTextControl( r, NULL, NULL, "700", NULL ); + fTargetSizeControl->SetDivider( 0 ); + fTargetSizeControl->SetEnabled( false ); + fTargetSizeControl->SetModificationMessage( + new BMessage( RIP_TARGET_CONTROL ) ); + fVideoBox->AddChild( fTargetSizeControl ); + + /* 2-pass */ + r = BRect( 10, 125, fVideoBox->Bounds().Width() / 2, 140 ); + fTwoPassCheck = new BCheckBox( r, NULL, "2-pass encoding", NULL ); + fVideoBox->AddChild( fTwoPassCheck ); + + /* Crop */ + r = BRect( fVideoBox->Bounds().Width() - 120, 120, + fVideoBox->Bounds().Width() - 10, 140 ); + fCropButton = new BButton( r, NULL, "Crop & Resize...", + new BMessage( RIP_CROP_BUTTON ) ); + fVideoBox->AddChild( fCropButton ); + + /* Audio box */ + r = BRect( 10, 170, Bounds().Width() - 10, 290 ); + fAudioBox = new BBox( r ); + fAudioBox->SetLabel( "Audio" ); + AddChild( fAudioBox ); + + /* Language */ + r = BRect( 10, 15, fAudioBox->Bounds().Width() - 10, 35 ); + fLanguagePopUp = new BPopUpMenu( "" ); + fLanguageField = new BMenuField( r, NULL, "Language:", + fLanguagePopUp, true ); + fAudioBox->AddChild( fLanguageField ); + + /* Secondary language */ + r = BRect( 10, 40, fAudioBox->Bounds().Width() - 10, 60 ); + fSecondaryLanguagePopUp = new BPopUpMenu( "" ); + fSecondaryLanguageField = new BMenuField( r, NULL, "Secondary language:", + fSecondaryLanguagePopUp, true ); + fAudioBox->AddChild( fSecondaryLanguageField ); + + /* Audio codec */ + r = BRect( 10, 65, fAudioBox->Bounds().Width() - 10, 85 ); + fAudioCodecPopUp = new BPopUpMenu( "" ); + fAudioCodecField = new BMenuField( r, NULL, "Codec:", + fAudioCodecPopUp, true ); + fAudioBox->AddChild( fAudioCodecField ); + + /* Audio bitrate */ + r = BRect( 10, 90, fAudioBox->Bounds().Width() - 10, 110 ); + fAudioBitratePopUp = new BPopUpMenu( "" ); + fAudioBitrateField = new BMenuField( r, NULL, "Bitrate:", + fAudioBitratePopUp, true ); + fAudioBox->AddChild( fAudioBitrateField ); + + /* Destination box */ + r = BRect( 10, 300, Bounds().Width() - 10, 395 ); + fDestinationBox = new BBox( r ); + fDestinationBox->SetLabel( "Destination" ); + AddChild( fDestinationBox ); + + /* File format */ + r = BRect( 10, 15, fDestinationBox->Bounds().Width() - 10, 35 ); + fFileFormatPopUp = new BPopUpMenu( "" ); + fFileFormatField = new BMenuField( r, NULL, "File format:", + fFileFormatPopUp, true ); + fDestinationBox->AddChild( fFileFormatField ); + + /* File location */ + r = BRect( 10, 40, fDestinationBox->Bounds().Width() - 10, 60 ); + fFileControl = new BTextControl( r, NULL, "Location:", + DEFAULT_FILE, NULL ); + fFileControl->SetDivider( 100 ); + fDestinationBox->AddChild( fFileControl ); + + /* Browse button */ + r = BRect( fDestinationBox->Bounds().Width() - 80, 65, + fDestinationBox->Bounds().Width() - 10, 85 ); + fFileButton = new BButton( r, NULL, "Browse...", + new BMessage( RIP_BROWSE_BUTTON ) ); + fDestinationBox->AddChild( fFileButton ); + + fFilePanel = new BFilePanel( B_SAVE_PANEL, NULL, NULL, 0, false ); + + /* Status bar */ + r = BRect( 10, 405, Bounds().Width() - 10, 435 ); + fStatusBar = new BStatusBar( r, NULL ); + AddChild( fStatusBar ); + + /* Suspend/Rip buttons */ + r = BRect( Bounds().Width() - 180, 445, + Bounds().Width() - 100, 465 ); + fSuspendButton = new BButton( r, NULL, "Suspend", + new BMessage( RIP_SUSPEND_BUTTON ) ); + fSuspendButton->SetEnabled( false ); + AddChild( fSuspendButton ); + r = BRect( Bounds().Width() - 90, 445, + Bounds().Width() - 10, 465 ); + fStartButton = new BButton( r, NULL, "Rip !", + new BMessage( RIP_RIP_BUTTON ) ); + fStartButton->MakeDefault( true ); + AddChild( fStartButton ); + + /* Fill popups */ + fVideoCodecPopUp->AddItem( new BMenuItem( "MPEG-4", NULL ) ); + fVideoCodecPopUp->ItemAt( 0 )->SetMarked( true ); + fAudioCodecPopUp->AddItem( new BMenuItem( "MP3", NULL ) ); + fAudioCodecPopUp->ItemAt( 0 )->SetMarked( true ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "32", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "64", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "96", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "128", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "160", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "192", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "224", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "256", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "288", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->AddItem( + new BMenuItem( "320", new BMessage( RIP_TARGET_CONTROL ) ) ); + fAudioBitratePopUp->ItemAt( 3 )->SetMarked( true ); + fFileFormatPopUp->AddItem( new BMenuItem( "AVI", NULL ) ); + fFileFormatPopUp->ItemAt( 0 )->SetMarked( true ); +} + +void RipView::MessageReceived( BMessage * message ) +{ + switch( message->what ) + { + case RIP_TITLE_POPUP: + { + int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); + HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + + /* Empty current popups */ + BMenuItem * item; + while( ( item = fLanguagePopUp->ItemAt( 0 ) ) ) + { + fLanguagePopUp->RemoveItem( item ); + delete item; + } + while( ( item = fSecondaryLanguagePopUp->ItemAt( 0 ) ) ) + { + fSecondaryLanguagePopUp->RemoveItem( item ); + delete item; + } + + /* Show new languages */ + HBAudio * audio; + for( uint32_t i = 0; i < title->fAudioList->CountItems(); i++ ) + { + audio = (HBAudio*) title->fAudioList->ItemAt( i ); + fLanguagePopUp->AddItem( + new BMenuItem( audio->fDescription, NULL ) ); + fSecondaryLanguagePopUp->AddItem( + new BMenuItem( audio->fDescription, + new BMessage( RIP_TARGET_CONTROL ) ) ); + } + fLanguagePopUp->ItemAt( 0 )->SetMarked( true ); + fSecondaryLanguagePopUp->AddItem( new BMenuItem( "None", + new BMessage( RIP_TARGET_CONTROL ) ) ); + fSecondaryLanguagePopUp->ItemAt( + fSecondaryLanguagePopUp->CountItems() - 1 )->SetMarked( true ); + + fSecondaryLanguageField->SetEnabled( + ( title->fAudioList->CountItems() > 1 ) ); + + break; + } + + case RIP_BITRATE_RADIO: + { + if( fCustomBitrateRadio->Value() ) + { + fCustomBitrateControl->SetEnabled( true ); + fTargetSizeControl->SetEnabled( false ); + } + else + { + fCustomBitrateControl->SetEnabled( false ); + fTargetSizeControl->SetEnabled( true ); + Window()->PostMessage( RIP_TARGET_CONTROL ); + } + break; + } + + case RIP_TARGET_CONTROL: + { + if( !fTargetSizeRadio->Value() ) + { + break; + } + + int64_t available; + int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); + HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + + available = (int64_t) 1024 * 1024 * + atoi( fTargetSizeControl->Text() ); + + /* AVI headers */ + available -= 2048; + + /* Video chunk headers (8 bytes / frame) and + and index (16 bytes / frame) */ + available -= 24 * title->fLength * title->fRate / + title->fScale; + + /* Audio tracks */ + available -= + ( strcmp( fSecondaryLanguagePopUp->FindMarked()->Label(), + "None" ) ? 2 : 1 ) * + ( title->fLength * + atoi( fAudioBitratePopUp->FindMarked()->Label() ) * 128 + + 24 * title->fLength * 44100 / 1152 ); + + char string[1024]; memset( string, 0, 1024 ); + if( available < 0 ) + { + sprintf( string, "0" ); + } + else + { + sprintf( string, "%lld", available / + ( 128 * title->fLength ) ); + } + fCustomBitrateControl->SetText( string ); + break; + } + + case RIP_CROP_BUTTON: + { + int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); + HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + + HBPictureWin * win; + win = new HBPictureWin( fManager, title ); + win->Show(); + break; + } + + case RIP_BROWSE_BUTTON: + { + fFilePanel->Show(); + } + + case B_SAVE_REQUESTED: + { + entry_ref ref; + BString string; + if( message->FindRef( "directory", 0, &ref ) == B_OK && + message->FindString( "name", &string ) == B_OK ) + { + BPath * path = new BPath( &ref ); + string.Prepend( "/" ); + string.Prepend( path->Path() ); + fFileControl->SetText( string.String() ); + } + break; + } + + case RIP_SUSPEND_BUTTON: + { + if( strcmp( fSuspendButton->Label(), "Suspend" ) ) + { + fManager->ResumeRip(); + } + else + { + fManager->SuspendRip(); + } + + break; + } + + case RIP_RIP_BUTTON: + { + if( strcmp( fStartButton->Label(), "Rip !" ) ) + { + fManager->StopRip(); + } + else + { + int index; + + /* Get asked title & languages */ + index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); + HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + index = fLanguagePopUp->IndexOf( fLanguagePopUp->FindMarked() ); + HBAudio * audio1 = + (HBAudio*) title->fAudioList->ItemAt( index ); + index = fSecondaryLanguagePopUp->IndexOf( + fSecondaryLanguagePopUp->FindMarked() ); + HBAudio * audio2 = + (HBAudio*) title->fAudioList->ItemAt( index ); + + /* Use user settings */ + title->fBitrate = atoi( fCustomBitrateControl->Text() ); + title->fTwoPass = ( fTwoPassCheck->Value() != 0 ); + audio1->fOutBitrate = + atoi( fAudioBitratePopUp->FindMarked()->Label() ); + if( audio2 ) + { + audio2->fOutBitrate = + atoi( fAudioBitratePopUp->FindMarked()->Label() ); + } + + /* Let libhb do the job */ + fManager->StartRip( title, audio1, audio2, + (char*) fFileControl->Text() ); + } + break; + } + + default: + BView::MessageReceived( message ); + break; + } +} + +void RipView::UpdateIntf( HBStatus status ) +{ + switch( status.fMode ) + { + case HB_MODE_READY_TO_RIP: + { + fTitleList = status.fTitleList; + + 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->AddItem( + new BMenuItem( string, new BMessage( RIP_TITLE_POPUP ) ) ); + } + fTitlePopUp->ItemAt( 0 )->SetMarked( true ); + Window()->PostMessage( RIP_TITLE_POPUP ); + break; + } + + case HB_MODE_ENCODING: + { + fTitleField->SetEnabled( false ); + fVideoCodecField->SetEnabled( false ); + fCustomBitrateRadio->SetEnabled( false ); + fCustomBitrateControl->SetEnabled( false ); + fTargetSizeRadio->SetEnabled( false ); + fTargetSizeControl->SetEnabled( false ); + fTwoPassCheck->SetEnabled( false ); + fCropButton->SetEnabled( false ); + fLanguageField->SetEnabled( false ); + fSecondaryLanguageField->SetEnabled( false ); + fAudioCodecField->SetEnabled( false ); + fAudioBitrateField->SetEnabled( false ); + fFileFormatField->SetEnabled( false ); + fFileControl->SetEnabled( false ); + fFileButton->SetEnabled( false ); + + if( !status.fPosition ) + { + fStatusBar->Update( - fStatusBar->CurrentValue(), + "Starting..." ); + } + 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 ); + fStatusBar->Update( 100 * status.fPosition - + fStatusBar->CurrentValue(), + string ); + } + + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( true ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->SetEnabled( true ); + break; + } + + case HB_MODE_SUSPENDED: + { + fTitleField->SetEnabled( false ); + fVideoCodecField->SetEnabled( false ); + fCustomBitrateRadio->SetEnabled( false ); + fCustomBitrateControl->SetEnabled( false ); + fTargetSizeRadio->SetEnabled( false ); + fTargetSizeControl->SetEnabled( false ); + fTwoPassCheck->SetEnabled( false ); + fCropButton->SetEnabled( false ); + fLanguageField->SetEnabled( false ); + fSecondaryLanguageField->SetEnabled( false ); + fAudioCodecField->SetEnabled( false ); + fAudioBitrateField->SetEnabled( false ); + fFileFormatField->SetEnabled( false ); + fFileControl->SetEnabled( false ); + fFileButton->SetEnabled( false ); + + fStatusBar->Update( 100 * status.fPosition - + fStatusBar->CurrentValue(), "Suspended" ); + + fSuspendButton->SetLabel( "Resume" ); + fSuspendButton->SetEnabled( true ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->SetEnabled( true ); + break; + } + + case HB_MODE_STOPPING: + { + fTitleField->SetEnabled( false ); + fVideoCodecField->SetEnabled( false ); + fCustomBitrateRadio->SetEnabled( false ); + fCustomBitrateControl->SetEnabled( false ); + fTargetSizeRadio->SetEnabled( false ); + fTargetSizeControl->SetEnabled( false ); + fTwoPassCheck->SetEnabled( false ); + fCropButton->SetEnabled( false ); + fLanguageField->SetEnabled( false ); + fSecondaryLanguageField->SetEnabled( false ); + fAudioCodecField->SetEnabled( false ); + fAudioBitrateField->SetEnabled( false ); + fFileFormatField->SetEnabled( false ); + fFileControl->SetEnabled( false ); + fFileButton->SetEnabled( false ); + + fStatusBar->Update( - fStatusBar->CurrentValue(), + "Stopping..." ); + + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->SetEnabled( false ); + break; + } + + case HB_MODE_DONE: + { + fTitleField->SetEnabled( true ); + fVideoCodecField->SetEnabled( true ); + fCustomBitrateRadio->SetEnabled( true ); + fCustomBitrateControl->SetEnabled( fCustomBitrateRadio->Value() ); + fTargetSizeRadio->SetEnabled( true ); + fTargetSizeControl->SetEnabled( fTargetSizeRadio->Value() ); + fTwoPassCheck->SetEnabled( true ); + fCropButton->SetEnabled( true ); + fLanguageField->SetEnabled( true ); + fSecondaryLanguageField->SetEnabled( + ( fSecondaryLanguagePopUp->CountItems() > 2 ) ); + fAudioCodecField->SetEnabled( true ); + fAudioBitrateField->SetEnabled( true ); + fFileFormatField->SetEnabled( true ); + fFileControl->SetEnabled( true ); + fFileButton->SetEnabled( true ); + + fStatusBar->Update( 100.0 - fStatusBar->CurrentValue(), + "Done." ); + + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Rip !" ); + fStartButton->SetEnabled( true ); + break; + } + + case HB_MODE_CANCELED: + { + fTitleField->SetEnabled( true ); + fVideoCodecField->SetEnabled( true ); + fCustomBitrateRadio->SetEnabled( true ); + fCustomBitrateControl->SetEnabled( fCustomBitrateRadio->Value() ); + fTargetSizeRadio->SetEnabled( true ); + fTargetSizeControl->SetEnabled( fTargetSizeRadio->Value() ); + fTwoPassCheck->SetEnabled( true ); + fCropButton->SetEnabled( true ); + fLanguageField->SetEnabled( true ); + fSecondaryLanguageField->SetEnabled( + ( fSecondaryLanguagePopUp->CountItems() > 2 ) ); + fAudioCodecField->SetEnabled( true ); + fAudioBitrateField->SetEnabled( true ); + fFileFormatField->SetEnabled( true ); + fFileControl->SetEnabled( true ); + fFileButton->SetEnabled( true ); + + fStatusBar->Update( - fStatusBar->CurrentValue(), + "Canceled." ); + + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Rip !" ); + fStartButton->SetEnabled( true ); + break; + } + + case HB_MODE_ERROR: + { + fTitleField->SetEnabled( true ); + fVideoCodecField->SetEnabled( true ); + fCustomBitrateRadio->SetEnabled( true ); + fCustomBitrateControl->SetEnabled( fCustomBitrateRadio->Value() ); + fTargetSizeRadio->SetEnabled( true ); + fTargetSizeControl->SetEnabled( fTargetSizeRadio->Value() ); + fTwoPassCheck->SetEnabled( true ); + fCropButton->SetEnabled( true ); + fLanguageField->SetEnabled( true ); + fSecondaryLanguageField->SetEnabled( + ( fSecondaryLanguagePopUp->CountItems() > 2 ) ); + fAudioCodecField->SetEnabled( true ); + fAudioBitrateField->SetEnabled( true ); + fFileFormatField->SetEnabled( true ); + fFileControl->SetEnabled( true ); + fFileButton->SetEnabled( true ); + + fStatusBar->Update( - fStatusBar->CurrentValue(), + "Error." ); + + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Rip !" ); + fStartButton->SetEnabled( true ); + break; + } + + default: + break; + } +} + diff --git a/beos/RipView.h b/beos/RipView.h new file mode 100644 index 000000000..d487b2b99 --- /dev/null +++ b/beos/RipView.h @@ -0,0 +1,77 @@ +/* $Id: RipView.h,v 1.5 2003/10/13 22:23:02 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_RIP_VIEW_H +#define HB_RIP_VIEW_H + +#include <View.h> +class BBox; +class BButton; +class BCheckBox; +class BFilePanel; +class BMenuField; +class BPopUpMenu; +class BRadioButton; +class BStatusBar; +class BTextControl; + +#include "Common.h" + +#define RIP_TITLE_POPUP 'rtip' +#define RIP_BITRATE_RADIO 'rbir' +#define RIP_TARGET_CONTROL 'rtac' +#define RIP_CROP_BUTTON 'rcrb' +#define RIP_BROWSE_BUTTON 'rbrb' +#define RIP_SUSPEND_BUTTON 'rsub' +#define RIP_RIP_BUTTON 'rrib' + +class RipView : public BView +{ + public: + RipView( HBManager * manager ); + void MessageReceived( BMessage * message ); + void UpdateIntf( HBStatus status ); + + private: + HBManager * fManager; + HBList * fTitleList; + + BBox * fVideoBox; + BPopUpMenu * fTitlePopUp; + BMenuField * fTitleField; + BPopUpMenu * fVideoCodecPopUp; + BMenuField * fVideoCodecField; + BRadioButton * fCustomBitrateRadio; + BTextControl * fCustomBitrateControl; + BRadioButton * fTargetSizeRadio; + BTextControl * fTargetSizeControl; + BCheckBox * fTwoPassCheck; + BButton * fCropButton; + + BBox * fAudioBox; + BPopUpMenu * fLanguagePopUp; + BMenuField * fLanguageField; + BPopUpMenu * fSecondaryLanguagePopUp; + BMenuField * fSecondaryLanguageField; + BPopUpMenu * fAudioCodecPopUp; + BMenuField * fAudioCodecField; + BPopUpMenu * fAudioBitratePopUp; + BMenuField * fAudioBitrateField; + + BBox * fDestinationBox; + BPopUpMenu * fFileFormatPopUp; + BMenuField * fFileFormatField; + BTextControl * fFileControl; + BButton * fFileButton; + BFilePanel * fFilePanel; + + BStatusBar * fStatusBar; + BButton * fSuspendButton; + BButton * fStartButton; +}; + +#endif diff --git a/beos/ScanView.cpp b/beos/ScanView.cpp new file mode 100644 index 000000000..fb5d722e8 --- /dev/null +++ b/beos/ScanView.cpp @@ -0,0 +1,280 @@ +/* $Id: ScanView.cpp,v 1.4 2003/10/13 23:42:03 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 <Box.h> +#include <Button.h> +#include <Directory.h> +#include <Drivers.h> +#include <FilePanel.h> +#include <MenuField.h> +#include <MenuItem.h> +#include <Path.h> +#include <PopUpMenu.h> +#include <Query.h> +#include <RadioButton.h> +#include <StringView.h> +#include <TextControl.h> +#include <VolumeRoster.h> + +#include "Manager.h" +#include "ScanView.h" + +ScanView::ScanView( HBManager * manager ) + : BView( BRect( 0,0,400,190 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW ) +{ + fManager = manager; + + BRect r; + SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); + + r = BRect( 10, 10, Bounds().Width() - 10, 115 ); + BBox * box = new BBox( r ); + box->SetLabel( "Select source:" ); + AddChild( box ); + + r = BRect( 10, 15, box->Bounds().Width() / 2, 35 ); + fRadioDetected = new BRadioButton( r, NULL, "Detected volume:", + new BMessage( SCAN_RADIO ) ); + box->AddChild( fRadioDetected ); + + r = BRect( box->Bounds().Width() / 2, 15, + box->Bounds().Width() - 10, 35 ); + fPopUp = new BPopUpMenu( "" ); + fField = new BMenuField( r, NULL, NULL, fPopUp, true ); + fField->SetDivider( 0 ); + box->AddChild( fField ); + + r = BRect( 10, 45, box->Bounds().Width() / 3, 65 ); + fRadioFolder = new BRadioButton( r, NULL, "DVD folder:", + new BMessage( SCAN_RADIO ) ); + box->AddChild( fRadioFolder ); + + r = BRect( box->Bounds().Width() / 3, 45, + box->Bounds().Width() - 10, 65 ); + fFolderControl = new BTextControl( r, NULL, NULL, NULL, NULL ); + box->AddChild( fFolderControl ); + + r = BRect( box->Bounds().Width() - 80, 70, + box->Bounds().Width() - 10, 95 ); + fBrowseButton = new BButton( r, NULL, "Browse...", + new BMessage( SCAN_BROWSE_BUTTON ) ); + box->AddChild( fBrowseButton ); + + fFilePanel = new BFilePanel( B_OPEN_PANEL, NULL, + NULL, B_DIRECTORY_NODE ); + + r = BRect( 10, 125, Bounds().Width() - 10, 145 ); + fStatusString = new BStringView( r, NULL, NULL ); + AddChild( fStatusString ); + + r = BRect( Bounds().Width() - 70, 155, + Bounds().Width() - 10, 175 ); + fOpenButton = new BButton( r, NULL, "Open", new BMessage( SCAN_OPEN ) ); + fOpenButton->MakeDefault( true ); + AddChild( fOpenButton ); + + DetectVolumes(); +} + +void ScanView::MessageReceived( BMessage * message ) +{ + switch( message->what ) + { + case SCAN_RADIO: + { + if( fRadioDetected->Value() ) + { + fField->SetEnabled( true ); + fFolderControl->SetEnabled( false ); + fBrowseButton->SetEnabled( false ); + fOpenButton->SetEnabled( fPopUp->CountItems() > 0 ); + } + else + { + fField->SetEnabled( false ); + fFolderControl->SetEnabled( true ); + fBrowseButton->SetEnabled( true ); + fOpenButton->SetEnabled( true ); + } + break; + } + + case SCAN_BROWSE_BUTTON: + { + fFilePanel->Show(); + break; + } + + case B_REFS_RECEIVED: + { + entry_ref ref; + if( message->FindRef( "refs", 0, &ref ) == B_OK ) + { + BPath * path = new BPath( &ref ); + fFolderControl->SetText( path->Path() ); + } + break; + } + + case SCAN_OPEN: + { + if( fRadioDetected->Value() ) + { + fManager->ScanVolumes( (char*) + fPopUp->FindMarked()->Label() ); + } + else + { + fManager->ScanVolumes( (char*) fFolderControl->Text() ); + } + break; + } + + default: + BView::MessageReceived( message ); + } +} + +void ScanView::UpdateIntf( HBStatus status ) +{ + switch( status.fMode ) + { + case HB_MODE_SCANNING: + { + fRadioDetected->SetEnabled( false ); + fRadioFolder->SetEnabled( false ); + fField->SetEnabled( false ); + fFolderControl->SetEnabled( false ); + fBrowseButton->SetEnabled( false ); + fOpenButton->SetEnabled( false ); + + char string[1024]; memset( string, 0, 1024 ); + if( !status.fScannedTitle ) + { + sprintf( string, "Opening %s...", + status.fScannedVolume ); + } + else + { + sprintf( string, "Scanning %s, title %d...", + status.fScannedVolume, status.fScannedTitle ); + } + fStatusString->SetText( string ); + break; + } + + case HB_MODE_INVALID_VOLUME: + { + fRadioDetected->SetEnabled( true ); + fRadioFolder->SetEnabled( true ); + + if( fRadioDetected->Value() ) + { + fField->SetEnabled( true ); + fFolderControl->SetEnabled( false ); + fBrowseButton->SetEnabled( false ); + fOpenButton->SetEnabled( fPopUp->CountItems() > 0 ); + } + else + { + fField->SetEnabled( false ); + fFolderControl->SetEnabled( true ); + fBrowseButton->SetEnabled( true ); + fOpenButton->SetEnabled( true ); + } + + fStatusString->SetText( "Invalid volume." ); + break; + } + + default: + break; + } +} + +void ScanView::DetectVolumes() +{ + BVolumeRoster * roster = new BVolumeRoster(); + BVolume * volume = new BVolume(); + fs_info info; + int device; + device_geometry geometry; + + /* Parse mounted volumes */ + 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 */ + fPopUp->AddItem( new BMenuItem( info.device_name, NULL ) ); + } + 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 ); + + fPopUp->AddItem( new BMenuItem( path.Path(), NULL ) ); + } + + delete query; + } + } + + if( fPopUp->CountItems() > 0 ) + { + fPopUp->ItemAt( 0 )->SetMarked( true ); + fRadioDetected->SetValue( true ); + fFolderControl->SetEnabled( false ); + fBrowseButton->SetEnabled( false ); + } + else + { + fRadioFolder->SetValue( true ); + fField->SetEnabled( false ); + } +} + diff --git a/beos/ScanView.h b/beos/ScanView.h new file mode 100644 index 000000000..5e2514b54 --- /dev/null +++ b/beos/ScanView.h @@ -0,0 +1,48 @@ +/* $Id: ScanView.h,v 1.2 2003/10/13 22:23:02 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_SCAN_VIEW_H +#define HB_SCAN_VIEW_H + +#include <View.h> +class BButton; +class BFilePanel; +class BMenuField; +class BPopUpMenu; +class BRadioButton; +class BStringView; +class BTextControl; + +#include "Common.h" + +#define SCAN_RADIO 'scra' +#define SCAN_BROWSE_BUTTON 'sbrb' +#define SCAN_OPEN 'scop' + +class ScanView : public BView +{ + public: + ScanView( HBManager * manager ); + void MessageReceived( BMessage * message ); + void UpdateIntf( HBStatus status ); + + private: + void DetectVolumes(); + + HBManager * fManager; + + BRadioButton * fRadioDetected; + BRadioButton * fRadioFolder; + BMenuField * fField; + BPopUpMenu * fPopUp; + BTextControl * fFolderControl; + BButton * fBrowseButton; + BFilePanel * fFilePanel; + BStringView * fStatusString; + BButton * fOpenButton; +}; + +#endif diff --git a/core/Ac3Decoder.cpp b/core/Ac3Decoder.cpp index 12eed05df..95030d810 100644 --- a/core/Ac3Decoder.cpp +++ b/core/Ac3Decoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Ac3Decoder.cpp,v 1.12 2003/09/30 14:38:15 titer Exp $ +/* $Id: Ac3Decoder.cpp,v 1.20 2003/10/13 10:58:24 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -13,101 +13,160 @@ extern "C" { } HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudio * audio ) - : HBThread( "ac3decoder" ) { - fManager = manager; - fAudio = audio; + fManager = manager; + fAudio = audio; + fLock = new HBLock(); + fUsed = false; + + /* Init liba52 */ + fState = a52_init( 0 ); + fInFlags = 0; + fOutFlags = A52_STEREO; + + /* Lame wants samples from -32768 to 32768 */ + fSampleLevel = 32768.0; + /* Max size for a A52 frame is 3840 bytes */ - fAc3Frame = new HBBuffer( 3840 ); - fAc3Buffer = NULL; - fPosInBuffer = 0; - fPosition = 0; + fAc3Frame = new HBBuffer( 3840 ); + fAc3Frame->fSize = 0; + fAc3Buffer = NULL; + fPosInBuffer = 0; + fRawBuffer = NULL; } HBAc3Decoder::~HBAc3Decoder() { + if( fRawBuffer ) delete fRawBuffer; + if( fAc3Buffer ) delete fAc3Buffer; delete fAc3Frame; + a52_free( fState ); + delete fLock; } -void HBAc3Decoder::DoWork() +bool HBAc3Decoder::Work() { - /* Init liba52 */ - a52_state_t * state = a52_init( 0 ); - int inFlags = 0; - int outFlags = A52_STEREO; - - /* Lame wants samples from -32768 to 32768 */ - float sampleLevel = 32768; - - int frameSize; - HBBuffer * rawBuffer; - sample_t * samples; - - /* Main loop */ + if( !Lock() ) + { + return false; + } + + bool didSomething = false; + + sample_t * samples; for( ;; ) { - while( fSuspend ) + /* Try to push the latest decoded buffer */ + if( fRawBuffer ) { - Snooze( 10000 ); + if( fAudio->fRawFifo->Push( fRawBuffer ) ) + { + fRawBuffer = NULL; + } + else + { + break; + } } - fAc3Frame->fSize = 0; - - /* Get a frame header (7 bytes) */ - if( !( GetBytes( 7 ) ) ) + /* Get a new frame */ + if( fAc3Frame->fSize < 7 ) { - break; - } - - /* Get the size of the current frame */ - frameSize = a52_syncinfo( fAc3Frame->fData, &inFlags, - &fAudio->fInSampleRate, - &fAudio->fInBitrate ); + /* Get a frame header (7 bytes) */ + if( !( GetBytes( 7 ) ) ) + { + break; + } - if( !frameSize ) - { - Log( "HBAc3Decoder : a52_syncinfo failed" ); - fManager->Error(); - break; + /* Get the size of the current frame */ + fFrameSize = a52_syncinfo( fAc3Frame->fData, &fInFlags, + &fAudio->fInSampleRate, + &fAudio->fInBitrate ); + if( !fFrameSize ) + { + Log( "HBAc3Decoder : a52_syncinfo failed" ); + fManager->Error( HB_ERROR_A52_SYNC ); + return false; + } } - /* Get the whole frame */ - if( !( GetBytes( (uint32_t) frameSize ) ) ) + /* In case the audio should start later than the video, + insert some silence */ + if( fAudio->fDelay > 3 * 256 * 1000 / fAudio->fInSampleRate ) { - break; + fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) ); + for( uint32_t i = 0; i < 12 * 256; i++ ) + { + ((float*)fRawBuffer->fData)[i] = 0; + } + fAudio->fDelay -= 6 * 256 * 1000 / fAudio->fInSampleRate; + continue; } + + if( fAc3Frame->fSize >= 7 ) + { + /* Get the whole frame */ + if( !( GetBytes( (uint32_t) fFrameSize ) ) ) + { + break; + } - /* Feed liba52 */ - a52_frame( state, fAc3Frame->fData, &outFlags, &sampleLevel, 0 ); + /* Feed liba52 */ + a52_frame( fState, fAc3Frame->fData, &fOutFlags, + &fSampleLevel, 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 ); + /* 6 blocks per frame, 256 samples per block */ + fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) ); + fRawBuffer->fPosition = fPosition; + for( int i = 0; i < 6; i++ ) + { + /* Decode a block */ + a52_block( fState ); - /* Get a pointer to the raw data */ - samples = a52_samples( state ); + /* Get a pointer to the raw data */ + samples = a52_samples( fState ); - /* Copy left channel data */ - memcpy( (float*) rawBuffer->fData + i * 256, - samples, - 256 * sizeof( float ) ); + /* Copy left channel data */ + memcpy( (float*) fRawBuffer->fData + i * 256, + samples, + 256 * sizeof( float ) ); - /* Copy right channel data */ - memcpy( (float*) rawBuffer->fData + ( 6 + i ) * 256, - samples + 256, - 256 * sizeof( float ) ); - } + /* Copy right channel data */ + memcpy( (float*) fRawBuffer->fData + ( 6 + i ) * 256, + samples + 256, + 256 * sizeof( float ) ); + } - if( !Push( fAudio->fRawFifo, rawBuffer ) ) - { - break; + fAc3Frame->fSize = 0; + + didSomething = true; } } + + Unlock(); + + return didSomething; +} + +bool HBAc3Decoder::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBAc3Decoder::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } /* GetBytes() : pops buffers from the AC3 fifo until fAc3Frame @@ -118,7 +177,7 @@ bool HBAc3Decoder::GetBytes( uint32_t size ) { if( !fAc3Buffer ) { - if( !( fAc3Buffer = Pop( fAudio->fAc3Fifo ) ) ) + if( !( fAc3Buffer = fAudio->fAc3Fifo->Pop() ) ) { return false; } diff --git a/core/Ac3Decoder.h b/core/Ac3Decoder.h index 8226bb365..41ac48395 100644 --- a/core/Ac3Decoder.h +++ b/core/Ac3Decoder.h @@ -1,4 +1,4 @@ -/* $Id: Ac3Decoder.h,v 1.6 2003/09/30 14:38:15 titer Exp $ +/* $Id: Ac3Decoder.h,v 1.10 2003/10/07 20:58:12 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,26 +8,40 @@ #define HB_AC3_DECODER_H #include "Common.h" -#include "Thread.h" -class HBAc3Decoder : public HBThread +class HBAc3Decoder { public: - HBAc3Decoder( HBManager * manager, - HBAudio * audio ); - ~HBAc3Decoder(); + HBAc3Decoder( HBManager * manager, + HBAudio * audio ); + ~HBAc3Decoder(); + bool Work(); private: - void DoWork(); - bool GetBytes( uint32_t size ); - - HBManager * fManager; - HBAudio * fAudio; - - HBBuffer * fAc3Frame; - HBBuffer * fAc3Buffer; - uint32_t fPosInBuffer; - float fPosition; + bool Lock(); + void Unlock(); + bool GetBytes( uint32_t size ); + + HBManager * fManager; + HBAudio * fAudio; + + HBLock * fLock; + bool fUsed; + + /* liba52 */ + a52_state_t * fState; + int fInFlags; + int fOutFlags; + float fSampleLevel; + + /* buffers */ + HBBuffer * fAc3Frame; + HBBuffer * fAc3Buffer; + uint32_t fPosInBuffer; + HBBuffer * fRawBuffer; + + float fPosition; + int fFrameSize; }; #endif diff --git a/core/AviMuxer.cpp b/core/AviMuxer.cpp index 3b77b9c53..4a84fe8b8 100644 --- a/core/AviMuxer.cpp +++ b/core/AviMuxer.cpp @@ -1,4 +1,4 @@ -/* $Id: AviMuxer.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $ +/* $Id: AviMuxer.cpp,v 1.17 2003/10/09 23:33:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -149,7 +149,7 @@ void HBAviIndex::WriteInt32( uint32_t val ) HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title, HBAudio * audio1, HBAudio * audio2, char * fileName ) - : HBThread( "avimuxer" ) + : HBThread( "avimuxer", HB_NORMAL_PRIORITY ) { fManager = manager; fTitle = title; @@ -163,6 +163,8 @@ HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title, fRiffBytesCount = 2040; fMoviBytesCount = 4; + + Run(); } void HBAviMuxer::DoWork() @@ -171,7 +173,7 @@ void HBAviMuxer::DoWork() if( !( fFile = fopen( fFileName, "w" ) ) ) { Log( "HBAviMuxer: fopen failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_AVI_WRITE ); return; } diff --git a/core/Common.cpp b/core/Common.cpp index b9bb3e062..4087a001d 100644 --- a/core/Common.cpp +++ b/core/Common.cpp @@ -1,4 +1,4 @@ -/* $Id: Common.cpp,v 1.29 2003/09/30 21:21:32 titer Exp $ +/* $Id: Common.cpp,v 1.31 2003/10/07 22:48:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -92,6 +92,74 @@ uint64_t GetDate() return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec ); } +int GetCPUCount() +{ + int CPUCount = 1; + +#if defined( SYS_BEOS ) + system_info info; + get_system_info( &info ); + CPUCount = info.cpu_count; + +#elif defined( SYS_MACOSX ) + FILE * info; + char buffer[256]; + + if( ( info = popen( "/usr/sbin/sysctl hw.ncpu", "r" ) ) ) + { + if( fgets( buffer, 256, info ) ) + { + int count; + if( sscanf( buffer, "hw.ncpu: %d", &count ) == 1 ) + { + CPUCount = count; + } + else + { + Log( "GetCPUCount: sscanf() failed" ); + } + } + else + { + Log( "GetCPUCount: fgets() failed" ); + } + fclose( info ); + } + else + { + Log( "GetCPUCount: popen() failed" ); + } + +#elif defined( SYS_LINUX ) + FILE * info; + char buffer[256]; + + if( ( info = fopen( "/proc/cpuinfo", "r" ) ) ) + { + int count = 0; + while( fgets( buffer, 256, info ) ) + { + if( !memcmp( buffer, "processor", + sizeof( "processor" ) - 1 ) ) + { + count++; + } + } + CPUCount = count; + fclose( info ); + } + else + { + Log( "GetCPUCount: fopen() failed" ); + } + +#endif + CPUCount = MAX( 1, CPUCount ); + CPUCount = MIN( CPUCount, 8 ); + + return CPUCount; +} + #define HBLIST_DEFAULT_SIZE 20 HBList::HBList() diff --git a/core/Common.h b/core/Common.h index f4d40c8bd..3c138e2a1 100644 --- a/core/Common.h +++ b/core/Common.h @@ -1,4 +1,4 @@ -/* $Id: Common.h,v 1.28 2003/10/03 16:18:08 titer Exp $ +/* $Id: Common.h,v 1.34 2003/10/13 17:49:58 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -16,6 +16,8 @@ typedef uint8_t byte_t; /* Misc structures */ +typedef struct a52_state_s a52_state_t; +typedef struct lame_global_struct lame_global_flags; typedef struct dvdplay_s * dvdplay_ptr; typedef struct mpeg2dec_s mpeg2dec_t; typedef struct AVPicture AVPicture; @@ -43,6 +45,7 @@ class HBScanner; class HBStatus; class HBThread; class HBTitle; +class HBWorker; /* Handy macros */ #ifndef MIN @@ -61,22 +64,36 @@ void Snooze( uint64_t time ); void Log( char * log, ... ); char * LanguageForCode( int code ); uint64_t GetDate(); +int GetCPUCount(); /* 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 + HB_MODE_UNDEF = 00000, + HB_MODE_NEED_VOLUME = 00001, + HB_MODE_SCANNING = 00002, + HB_MODE_INVALID_VOLUME = 00004, + HB_MODE_READY_TO_RIP = 00010, + HB_MODE_ENCODING = 00020, + HB_MODE_SUSPENDED = 00040, + HB_MODE_STOPPING = 00100, + HB_MODE_DONE = 00200, + HB_MODE_CANCELED = 00400, + HB_MODE_ERROR = 01000 } HBMode; +/* Possible errors */ +typedef enum +{ + HB_ERROR_A52_SYNC = 0, + HB_ERROR_AVI_WRITE, + HB_ERROR_DVD_OPEN, + HB_ERROR_DVD_READ, + HB_ERROR_MP3_INIT, + HB_ERROR_MP3_ENCODE, + HB_ERROR_MPEG4_INIT +} HBError; + class HBStatus { public: @@ -96,6 +113,9 @@ class HBStatus uint64_t fStartDate; uint32_t fRemainingTime; /* in seconds */ uint64_t fSuspendDate; + + /* HB_MODE_ERROR */ + HBError fError; }; class HBList @@ -130,6 +150,8 @@ class HBAudio int fInBitrate; int fOutBitrate; + int64_t fDelay; /* in ms */ + /* Fifos */ HBFifo * fAc3Fifo; HBFifo * fRawFifo; @@ -187,6 +209,7 @@ class HBTitle HBResizer * fResizer; HBMpeg4Encoder * fMpeg4Encoder; HBAviMuxer * fAviMuxer; + HBWorker * fWorkers[4]; }; #endif diff --git a/core/DVDReader.cpp b/core/DVDReader.cpp index 27c20d08a..8f7835f51 100644 --- a/core/DVDReader.cpp +++ b/core/DVDReader.cpp @@ -1,4 +1,4 @@ -/* $Id: DVDReader.cpp,v 1.12 2003/10/03 16:49:19 titer Exp $ +/* $Id: DVDReader.cpp,v 1.17 2003/10/09 23:33:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -15,10 +15,12 @@ #include <dvdplay/nav.h> HBDVDReader::HBDVDReader( HBManager * manager, HBTitle * title ) - : HBThread( "dvdreader" ) + : HBThread( "dvdreader", HB_NORMAL_PRIORITY ) { fManager = manager; fTitle = title; + + Run(); } void HBDVDReader::DoWork() @@ -29,7 +31,7 @@ void HBDVDReader::DoWork() if( !vmg ) { Log( "HBDVDReader: dvdplay_open() failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_DVD_OPEN ); return; } @@ -69,7 +71,7 @@ void HBDVDReader::DoWork() { Log( "HBDVDReader: could not dvdplay_read()" ); delete dvdBuffer; - fManager->Error(); + fManager->Error( HB_ERROR_DVD_READ ); break; } diff --git a/core/Fifo.cpp b/core/Fifo.cpp index 35bcb0449..d1d051c33 100644 --- a/core/Fifo.cpp +++ b/core/Fifo.cpp @@ -1,4 +1,4 @@ -/* $Id: Fifo.cpp,v 1.14 2003/10/02 15:44:52 titer Exp $ +/* $Id: Fifo.cpp,v 1.15 2003/10/13 14:12:18 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -51,7 +51,8 @@ HBFifo::HBFifo( int capacity ) HBFifo::~HBFifo() { - Log( "HBFifo::~HBFifo : trashing %d buffers", Size() ); + Log( "HBFifo::~HBFifo: trashing %d buffer%s", + Size(), Size() ? "s" : "" ); /* Empty the fifo */ while( fWhereToPush != fWhereToPop ) diff --git a/core/Manager.cpp b/core/Manager.cpp index 583bda36a..826ceea58 100644 --- a/core/Manager.cpp +++ b/core/Manager.cpp @@ -1,72 +1,103 @@ -/* $Id: Manager.cpp,v 1.47 2003/10/05 14:28:40 titer Exp $ +/* $Id: Manager.cpp,v 1.68 2003/10/13 23:42:03 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 "Ac3Decoder.h" +#include "AviMuxer.h" #include "DVDReader.h" -#include "MpegDemux.h" +#include "Fifo.h" +#include "Manager.h" +#include "Mp3Encoder.h" #include "Mpeg2Decoder.h" #include "Mpeg4Encoder.h" -#include "Ac3Decoder.h" -#include "Mp3Encoder.h" -#include "AviMuxer.h" +#include "MpegDemux.h" #include "Resizer.h" +#include "Scanner.h" +#include "Worker.h" #include <ffmpeg/avcodec.h> /* Public methods */ -HBManager::HBManager( bool debug ) - : HBThread( "manager" ) +HBManager::HBManager( bool debug, int cpuCount ) + : HBThread( "manager", HB_NORMAL_PRIORITY ) { - 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 ); + putenv( "HB_DEBUG=1" ); + } + + /* Check CPU count */ + if( !cpuCount ) + { + fCPUCount = GetCPUCount(); + Log( "HBManager::HBManager: %d CPU%s detected", fCPUCount, + ( fCPUCount > 1 ) ? "s" : "" ); } else { - unsetenv( "HB_DEBUG" ); + fCPUCount = cpuCount; + if( fCPUCount < 1 ) + { + Log( "HBManager::HBManager: invalid CPU count (%d), " + "using 1", fCPUCount ); + fCPUCount = 1; + } + else if( fCPUCount > 8 ) + { + Log( "HBManager::HBManager: invalid CPU count (%d), " + "using 8", fCPUCount ); + fCPUCount = 8; + } + Log( "HBManager::HBManager: user specified %d CPU%s", + fCPUCount, ( fCPUCount > 1 ) ? "s" : "" ); } - fCurTitle = NULL; - fCurAudio1 = NULL; - fCurAudio2 = NULL; - /* Init ffmpeg's libavcodec */ avcodec_init(); // register_avcodec( &mpeg4_encoder ); avcodec_register_all(); + /* Initialization */ + fStopScan = false; + fStopRip = false; + fRipDone = false; + fError = false; + + fScanner = NULL; + + fStatusLock = new HBLock(); + fStatus.fMode = HB_MODE_NEED_VOLUME; + fNeedUpdate = true; + + fCurTitle = NULL; + fCurAudio1 = NULL; + fCurAudio2 = NULL; + Run(); } HBManager::~HBManager() { /* Stop ripping if needed */ - StopRip(); - while( fStopRip ) + fStatusLock->Lock(); + if( fStatus.fMode == HB_MODE_ENCODING ) { - Snooze( 10000 ); - } + fStatusLock->Unlock(); - Stop(); + StopRip(); + while( fStopRip ) + { + Snooze( 10000 ); + } + } + else + { + fStatusLock->Unlock(); + } /* Stop scanning if needed */ if( fScanner ) @@ -76,24 +107,24 @@ HBManager::~HBManager() /* Remove temp files */ char command[1024]; memset( command, 0, 1024 ); - sprintf( command, "rm -f /tmp/HB.%d.*", fPid ); + sprintf( command, "rm -f /tmp/HB.%d.*", GetPid() ); system( command ); + + delete fStatusLock; } void HBManager::DoWork() { - fPid = (int) getpid(); - while( !fDie ) { - /* Terminate dying threads */ if( fStopScan ) { - fStopScan = false; - + /* Destroy the thread */ delete fScanner; fScanner = NULL; + /* Update interface */ + fStatusLock->Lock(); if( fStatus.fTitleList && fStatus.fTitleList->CountItems() ) { fStatus.fMode = HB_MODE_READY_TO_RIP; @@ -103,83 +134,47 @@ void HBManager::DoWork() fStatus.fMode = HB_MODE_INVALID_VOLUME; } fNeedUpdate = true; + fStatusLock->Unlock(); + + fStopScan = false; } - if( fStopRip || fError ) + if( fStopRip || fError || fRipDone ) { - delete fCurTitle->fDVDReader; - delete fCurTitle->fMpegDemux; - delete fCurTitle->fMpeg2Decoder; - delete fCurTitle->fResizer; - delete fCurTitle->fMpeg4Encoder; - delete fCurTitle->fAviMuxer; - - if( fCurAudio1 ) + if( fRipDone ) { - delete fCurAudio1->fAc3Decoder; - delete fCurAudio1->fMp3Encoder; + /* Wait a bit to avoid trashing frames in fifos - + That's kinda ugly */ + while( fCurTitle->fPSFifo->Size() || + ( fCurTitle->fMpeg2Fifo->Size() && + ( !fCurAudio1 || fCurAudio1->fAc3Fifo->Size() ) && + ( !fCurAudio2 || fCurAudio2->fAc3Fifo->Size() ) ) ) + { + Snooze( 10000 ); + } + Snooze( 500000 ); } - - 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() ) ) + else { - Snooze( 10000 ); + fStatusLock->Lock(); + fStatus.fMode = HB_MODE_STOPPING; + fNeedUpdate = true; + fStatusLock->Unlock(); } - - while( fCurTitle->fMpeg4Fifo->Size() && - ( !fCurAudio1 || fCurAudio1->fMp3Fifo->Size() ) && - ( !fCurAudio2 || fCurAudio2->fMp3Fifo->Size() ) ) + + /* Stop threads */ + delete fCurTitle->fDVDReader; + delete fCurTitle->fAviMuxer; + for( int i = 0; i < fCPUCount; i++ ) { - Snooze( 10000 ); + delete fCurTitle->fWorkers[i]; } - delete fCurTitle->fDVDReader; + /* Clean up */ delete fCurTitle->fMpegDemux; delete fCurTitle->fMpeg2Decoder; delete fCurTitle->fResizer; delete fCurTitle->fMpeg4Encoder; - delete fCurTitle->fAviMuxer; if( fCurAudio1 ) { @@ -193,6 +188,7 @@ void HBManager::DoWork() delete fCurAudio2->fMp3Encoder; } + /* Destroy fifos */ delete fCurTitle->fPSFifo; delete fCurTitle->fMpeg2Fifo; delete fCurTitle->fRawFifo; @@ -213,9 +209,16 @@ void HBManager::DoWork() delete fCurAudio2->fMp3Fifo; } - fStatus.fMode = HB_MODE_DONE; - fRipDone = false; + /* Update interface */ + fStatusLock->Lock(); + fStatus.fMode = fStopRip ? HB_MODE_CANCELED : + ( fError ? HB_MODE_ERROR : HB_MODE_DONE ); fNeedUpdate = true; + fStatusLock->Unlock(); + + fStopRip = false; + fError = false; + fRipDone = false; } Snooze( 10000 ); @@ -224,23 +227,25 @@ void HBManager::DoWork() bool HBManager::NeedUpdate() { + fStatusLock->Lock(); if( fNeedUpdate ) { fNeedUpdate = false; + fStatusLock->Unlock(); return true; } - + fStatusLock->Unlock(); + return false; } HBStatus HBManager::GetStatus() { - return fStatus; -} - -int HBManager::GetPid() -{ - return fPid; + fStatusLock->Lock(); + HBStatus status = fStatus; + fStatusLock->Unlock(); + + return status; } void HBManager::ScanVolumes( char * device ) @@ -254,12 +259,13 @@ void HBManager::ScanVolumes( char * device ) } fScanner = new HBScanner( this, device ); - fScanner->Run(); + fStatusLock->Lock(); fStatus.fMode = HB_MODE_SCANNING; fStatus.fScannedVolume = strdup( device ); fStatus.fScannedTitle = 0; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::StartRip( HBTitle * title, HBAudio * audio1, @@ -282,86 +288,77 @@ void HBManager::StartRip( HBTitle * title, HBAudio * audio1, FixPictureSettings( title ); - Log( "HBManager::StartRip : device: %s, title: %d", - title->fDevice, title->fIndex ); - Log( " - video : %dx%d -> %dx%d, bitrate = %d, 2-pass = %s", + Log( "HBManager::StartRip:" ); + Log( "- device: %s, title: %d", title->fDevice, title->fIndex ); + Log( "- video: %dx%d->%dx%d, bitrate=%d, 2-pass=%s, deinterlace=%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->fBitrate, title->fTwoPass ? "yes" : "no", + title->fDeinterlace ? "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 ); + 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 ); + Log( "- audio 2: lang = %s (%x), bitrate = %d", + audio2->fDescription, audio2->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(); + /* Create fifos */ + title->fPSFifo = new HBFifo( 256 ); + title->fMpeg2Fifo = new HBFifo( 256 ); + title->fRawFifo = new HBFifo( 4 ); + title->fResizedFifo = new HBFifo( 4 ); + title->fMpeg4Fifo = new HBFifo( 4 ); + if( audio1 ) + { + audio1->fAc3Fifo = new HBFifo( 256 ); + audio1->fRawFifo = new HBFifo( 4 ); + audio1->fMp3Fifo = new HBFifo( 4 ); + } + if( audio2 ) + { + audio2->fAc3Fifo = new HBFifo( 256 ); + audio2->fRawFifo = new HBFifo( 4 ); + audio2->fMp3Fifo = new HBFifo( 4 ); + } - title->fDVDReader = new HBDVDReader( this, title ); + /* Create decoders & encoders objects */ 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 ) + /* Create and launch the threads */ + title->fDVDReader = new HBDVDReader( this, title ); + title->fAviMuxer = new HBAviMuxer( this, title, audio1, audio2, + file ); + for( int i = 0; i < fCPUCount; i++ ) { - audio2->fAc3Decoder->Run(); - audio2->fMp3Encoder->Run(); + title->fWorkers[i] = new HBWorker( title, audio1, audio2 ); } - + fCurTitle = title; fCurAudio1 = audio1; fCurAudio2 = audio2; + fStatusLock->Lock(); fStatus.fMode = HB_MODE_ENCODING; fStatus.fPosition = 0; fStatus.fFrameRate = 0; @@ -370,6 +367,7 @@ void HBManager::StartRip( HBTitle * title, HBAudio * audio1, fStatus.fRemainingTime = 0; fStatus.fSuspendDate = 0; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::SuspendRip() @@ -382,27 +380,17 @@ void HBManager::SuspendRip() } fCurTitle->fDVDReader->Suspend(); - fCurTitle->fMpegDemux->Suspend(); - fCurTitle->fMpeg2Decoder->Suspend(); - fCurTitle->fResizer->Suspend(); - fCurTitle->fMpeg4Encoder->Suspend(); fCurTitle->fAviMuxer->Suspend(); - - if( fCurAudio1 ) + for( int i = 0; i < fCPUCount; i++ ) { - fCurAudio1->fAc3Decoder->Suspend(); - fCurAudio1->fMp3Encoder->Suspend(); - } - - if( fCurAudio2 ) - { - fCurAudio2->fAc3Decoder->Suspend(); - fCurAudio2->fMp3Encoder->Suspend(); + fCurTitle->fWorkers[i]->Suspend(); } + fStatusLock->Lock(); fStatus.fMode = HB_MODE_SUSPENDED; fStatus.fSuspendDate = GetDate(); fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::ResumeRip() @@ -415,27 +403,17 @@ void HBManager::ResumeRip() } 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 ) + for( int i = 0; i < fCPUCount; i++ ) { - fCurAudio2->fAc3Decoder->Resume(); - fCurAudio2->fMp3Encoder->Resume(); + fCurTitle->fWorkers[i]->Resume(); } + fStatusLock->Lock(); fStatus.fMode = HB_MODE_ENCODING; fStatus.fStartDate += GetDate() - fStatus.fSuspendDate; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::StopRip() @@ -448,25 +426,6 @@ void HBManager::StopRip() } /* 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; } @@ -545,7 +504,7 @@ uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image ) /* 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, + sprintf( fileName, "/tmp/HB.%d.%x.%d", GetPid(), (uint32_t) title, image); FILE * file = fopen( fileName, "r" ); fread( buf1, 3 * fInWidth * fInHeight / 2, 1, file ); @@ -632,10 +591,12 @@ uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image ) void HBManager::Scanning( char * volume, int title ) { + fStatusLock->Lock(); fStatus.fMode = HB_MODE_SCANNING; fStatus.fScannedVolume = volume; fStatus.fScannedTitle = title; fNeedUpdate = true; + fStatusLock->Unlock(); } void HBManager::ScanDone( HBList * titleList ) @@ -650,34 +611,14 @@ void HBManager::Done() fRipDone = true; } -void HBManager::Error() +void HBManager::Error( HBError 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(); - } - + fStatus.fError = error; fError = true; } @@ -695,6 +636,7 @@ void HBManager::SetPosition( float pos ) return; } + fStatusLock->Lock(); fStatus.fPosition = pos; fStatus.fFrameRate = (float) fStatus.fFrames / ( ( (float) ( GetDate() - fStatus.fStartDate ) ) / 1000000 ) ; @@ -703,5 +645,6 @@ void HBManager::SetPosition( float pos ) ( 1 - fStatus.fPosition ) / ( 1000000 * fStatus.fPosition ) ); fNeedUpdate = true; + fStatusLock->Unlock(); } diff --git a/core/Manager.h b/core/Manager.h index 8aa6cec3a..dc885e5f5 100644 --- a/core/Manager.h +++ b/core/Manager.h @@ -1,4 +1,4 @@ -/* $Id: Manager.h,v 1.27 2003/09/30 21:21:32 titer Exp $ +/* $Id: Manager.h,v 1.32 2003/10/08 22:20:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -13,7 +13,8 @@ class HBManager : public HBThread { public: - HBManager( bool debug = false ); + HBManager( bool debug = false, + int cpuCount = 0 ); ~HBManager(); void DoWork(); @@ -29,17 +30,17 @@ class HBManager : public HBThread 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 Error( HBError error ); void SetPosition( float pos ); private: void FixPictureSettings( HBTitle * title ); int fPid; + int fCPUCount; /* Booleans used in DoWork() */ bool fStopScan; @@ -51,8 +52,10 @@ class HBManager : public HBThread HBScanner * fScanner; /* Status infos */ + HBLock * fStatusLock; bool fNeedUpdate; HBStatus fStatus; + HBTitle * fCurTitle; HBAudio * fCurAudio1; HBAudio * fCurAudio2; diff --git a/core/Mp3Encoder.cpp b/core/Mp3Encoder.cpp index b4e9fe860..06d96af29 100644 --- a/core/Mp3Encoder.cpp +++ b/core/Mp3Encoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Mp3Encoder.cpp,v 1.7 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mp3Encoder.cpp,v 1.13 2003/10/08 15:00:20 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -11,113 +11,153 @@ #include <lame/lame.h> HBMp3Encoder::HBMp3Encoder( HBManager * manager, HBAudio * audio ) - : HBThread( "mp3encoder" ) { - fManager = manager; - fAudio = audio; + fManager = manager; + fAudio = audio; + + fLock = new HBLock(); + fUsed = false; fRawBuffer = NULL; fPosInBuffer = 0; + fSamplesNb = 0; fLeftSamples = NULL; fRightSamples = NULL; fPosition = 0; + fInitDone = false; + fMp3Buffer = NULL; } -void HBMp3Encoder::DoWork() +bool HBMp3Encoder::Work() { - /* Wait a first buffer so we are sure that - fAudio->fInSampleRate (set the AC3 decoder) is not garbage */ - while( !fDie && !fAudio->fRawFifo->Size() ) + if( !Lock() ) { - Snooze( 5000 ); + return false; } - - if( fDie ) + + if( !fInitDone ) { - return; - } + /* Wait for a first buffer so we know fAudio->fInSampleRate + is correct */ + if( !fAudio->fRawFifo->Size() ) + { + Unlock(); + return false; + } + + /* 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 */ + fCount = ( 1152 * fAudio->fInSampleRate ) / + ( 2 * fAudio->fOutSampleRate ); + + /* Init libmp3lame */ + fGlobalFlags = lame_init(); + lame_set_in_samplerate( fGlobalFlags, fAudio->fInSampleRate ); + lame_set_out_samplerate( fGlobalFlags, fAudio->fOutSampleRate ); + lame_set_brate( fGlobalFlags, fAudio->fOutBitrate ); + + if( lame_init_params( fGlobalFlags ) == -1 ) + { + Log( "HBMp3Encoder: lame_init_params() failed" ); + fManager->Error( HB_ERROR_MP3_INIT ); + return false; + } - /* 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 * fAudio->fInSampleRate ) / - ( 2 * fAudio->fOutSampleRate ); - - /* Init libmp3lame */ - lame_global_flags * globalFlags = lame_init(); - 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" ); - fManager->Error(); - return; - } + fLeftSamples = (float*) malloc( fCount * sizeof( float ) ); + fRightSamples = (float*) malloc( fCount * sizeof( float ) ); - fLeftSamples = (float*) malloc( count * sizeof( float ) ); - fRightSamples = (float*) malloc( count * sizeof( float ) ); + fInitDone = true; + } - HBBuffer * mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); + bool didSomething = false; - int ret; for( ;; ) { - while( fSuspend ) + if( fMp3Buffer ) { - Snooze( 10000 ); + if( fAudio->fMp3Fifo->Push( fMp3Buffer ) ) + { + fMp3Buffer = NULL; + } + else + { + break; + } } - + /* Get new samples */ - if( !GetSamples( count ) ) + if( !GetSamples() ) { break; } - ret = lame_encode_buffer_float( globalFlags, - fLeftSamples, fRightSamples, - count, mp3Buffer->fData, - mp3Buffer->fSize ); + int ret; + fMp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); + ret = lame_encode_buffer_float( fGlobalFlags, fLeftSamples, + fRightSamples, fCount, + fMp3Buffer->fData, + fMp3Buffer->fSize ); if( ret < 0 ) { /* Something wrong happened */ - Log( "HBMp3Encoder : lame_encode_buffer_float() failed (%d)", ret ); - fManager->Error(); - break; + Log( "HBMp3Encoder : lame_encode_buffer_float() failed " + "(%d)", ret ); + fManager->Error( HB_ERROR_MP3_ENCODE ); + return false; } else if( ret > 0 ) { /* We got something, send it to the muxer */ - mp3Buffer->fSize = ret; - mp3Buffer->fKeyFrame = true; - mp3Buffer->fPosition = fPosition; - Push( fAudio->fMp3Fifo, mp3Buffer ); - mp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); + fMp3Buffer->fSize = ret; + fMp3Buffer->fKeyFrame = true; + fMp3Buffer->fPosition = fPosition; } + else + { + delete fMp3Buffer; + fMp3Buffer = NULL; + } + fSamplesNb = 0; + + didSomething = true; } - /* Clean up */ - delete mp3Buffer; - free( fLeftSamples ); - free( fRightSamples ); + Unlock(); + return didSomething; +} - lame_close( globalFlags ); +bool HBMp3Encoder::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; } -bool HBMp3Encoder::GetSamples( uint32_t count ) +void HBMp3Encoder::Unlock() { - uint32_t samplesNb = 0; + fLock->Lock(); + fUsed = false; + fLock->Unlock(); +} - while( samplesNb < count ) +bool HBMp3Encoder::GetSamples() +{ + while( fSamplesNb < fCount ) { if( !fRawBuffer ) { - if( !( fRawBuffer = Pop( fAudio->fRawFifo ) ) ) + if( !( fRawBuffer = fAudio->fRawFifo->Pop() ) ) { return false; } @@ -126,16 +166,16 @@ bool HBMp3Encoder::GetSamples( uint32_t count ) fPosition = fRawBuffer->fPosition; } - int willCopy = MIN( count - samplesNb, 6 * 256 - fPosInBuffer ); + int willCopy = MIN( fCount - fSamplesNb, 6 * 256 - fPosInBuffer ); - memcpy( fLeftSamples + samplesNb, + memcpy( fLeftSamples + fSamplesNb, (float*) fRawBuffer->fData + fPosInBuffer, willCopy * sizeof( float ) ); - memcpy( fRightSamples + samplesNb, + memcpy( fRightSamples + fSamplesNb, (float*) fRawBuffer->fData + 6 * 256 + fPosInBuffer, willCopy * sizeof( float ) ); - samplesNb += willCopy; + fSamplesNb += willCopy; fPosInBuffer += willCopy; if( fPosInBuffer == 6 * 256 ) diff --git a/core/Mp3Encoder.h b/core/Mp3Encoder.h index 67b8647d5..fb8348961 100644 --- a/core/Mp3Encoder.h +++ b/core/Mp3Encoder.h @@ -1,4 +1,4 @@ -/* $Id: Mp3Encoder.h,v 1.5 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mp3Encoder.h,v 1.9 2003/10/07 22:48:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,27 +8,36 @@ #define HB_MP3_ENCODER_H #include "Common.h" -#include "Thread.h" -class HBMp3Encoder : public HBThread +class HBMp3Encoder { public: HBMp3Encoder( HBManager * manager, HBAudio * audio ); + bool Work(); private: - void DoWork(); - bool GetSamples( uint32_t count ); + bool Lock(); + void Unlock(); + bool GetSamples(); HBManager * fManager; HBAudio * fAudio; + HBLock * fLock; + bool fUsed; + HBBuffer * fRawBuffer; uint32_t fPosInBuffer; /* in samples */ + uint32_t fSamplesNb; float * fLeftSamples; float * fRightSamples; float fPosition; + lame_global_flags * fGlobalFlags; + bool fInitDone; + HBBuffer * fMp3Buffer; + uint32_t fCount; }; #endif diff --git a/core/Mpeg2Decoder.cpp b/core/Mpeg2Decoder.cpp index 1ba4945bc..3149931e8 100644 --- a/core/Mpeg2Decoder.cpp +++ b/core/Mpeg2Decoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Mpeg2Decoder.cpp,v 1.14 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg2Decoder.cpp,v 1.21 2003/10/09 14:21:21 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -14,55 +14,91 @@ extern "C" { #include <ffmpeg/avcodec.h> HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitle * title ) - : HBThread( "mpeg2decoder" ) { - fManager = manager; - fTitle = title; + fManager = manager; + fTitle = title; + + fLock = new HBLock(); + fUsed = false; + + fPass = 42; + fRawBuffer = NULL; + fRawBufferList = new HBList(); + fHandle = NULL; } -void HBMpeg2Decoder::DoWork() +bool HBMpeg2Decoder::Work() { - if( !( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) ) + fLock->Lock(); + if( fUsed ) { - return; + fLock->Unlock(); + return true; } + fUsed = true; + fLock->Unlock(); - fPass = fMpeg2Buffer->fPass; - Init(); - - do + bool didSomething = false; + + for( ;; ) { - while( fSuspend ) + /* Push decoded buffers */ + while( ( fRawBuffer = + (HBBuffer*) fRawBufferList->ItemAt( 0 ) ) ) + { + if( fTitle->fRawFifo->Push( fRawBuffer ) ) + { + fRawBufferList->RemoveItem( fRawBuffer ); + } + else + { + break; + } + } + + if( fRawBufferList->CountItems() ) { - Snooze( 10000 ); + break; + } + + /* Get a new buffer to decode */ + if( !( fMpeg2Buffer = fTitle->fMpeg2Fifo->Pop() ) ) + { + break; } + /* (Re)init if needed */ if( fMpeg2Buffer->fPass != fPass ) { - Close(); fPass = fMpeg2Buffer->fPass; Init(); } + /* Do the job */ DecodeBuffer(); + + didSomething = true; } - while( ( fMpeg2Buffer = Pop( fTitle->fMpeg2Fifo ) ) ); + + fLock->Lock(); + fUsed = false; + fLock->Unlock(); + + return didSomething; } void HBMpeg2Decoder::Init() { + if( fHandle ) + { + mpeg2_close( fHandle ); + } + 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 ); @@ -83,55 +119,52 @@ void HBMpeg2Decoder::DecodeBuffer() else if( ( state == STATE_SLICE || state == STATE_END ) && info->display_fbuf ) { - HBBuffer * rawBuffer = new HBBuffer( 3 * fTitle->fInWidth * - fTitle->fInHeight / 2 ); + fRawBuffer = new HBBuffer( 3 * fTitle->fInWidth * + fTitle->fInHeight / 2 ); /* TODO : make libmpeg2 write directly in our buffer */ - memcpy( rawBuffer->fData, + memcpy( fRawBuffer->fData, info->display_fbuf->buf[0], fTitle->fInWidth * fTitle->fInHeight ); - memcpy( rawBuffer->fData + fTitle->fInWidth * + memcpy( fRawBuffer->fData + fTitle->fInWidth * fTitle->fInHeight, info->display_fbuf->buf[1], fTitle->fInWidth * fTitle->fInHeight / 4 ); - memcpy( rawBuffer->fData + fTitle->fInWidth * + memcpy( fRawBuffer->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; + fRawBuffer->fPosition = fMpeg2Buffer->fPosition; + fRawBuffer->fPass = fMpeg2Buffer->fPass; + + fRawBufferList->AddItem( fRawBuffer ); /* 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 ); + HBBuffer * pulldownBuffer; + pulldownBuffer = new HBBuffer( fRawBuffer->fSize ); + pulldownBuffer->fPosition = fRawBuffer->fPosition; + pulldownBuffer->fPass = fRawBuffer->fPass; + memcpy( pulldownBuffer->fData, fRawBuffer->fData, + pulldownBuffer->fSize ); + fRawBufferList->AddItem( pulldownBuffer ); } 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" ); + Log( "HBMpeg2Decoder: STATE_INVALID" ); } } delete fMpeg2Buffer; + fMpeg2Buffer = NULL; } diff --git a/core/Mpeg2Decoder.h b/core/Mpeg2Decoder.h index 2e1a46b3d..9d1f27f8f 100644 --- a/core/Mpeg2Decoder.h +++ b/core/Mpeg2Decoder.h @@ -1,4 +1,4 @@ -/* $Id: Mpeg2Decoder.h,v 1.10 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg2Decoder.h,v 1.15 2003/10/09 14:21:21 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,25 +8,28 @@ #define HB_MPEG2_DECODER_H #include "Common.h" -#include "Thread.h" -class HBMpeg2Decoder : public HBThread +class HBMpeg2Decoder { public: HBMpeg2Decoder( HBManager * manager, HBTitle * title ); + bool Work(); private: - void DoWork(); void Init(); - void Close(); void DecodeBuffer(); HBManager * fManager; HBTitle * fTitle; + HBLock * fLock; + bool fUsed; + uint32_t fPass; HBBuffer * fMpeg2Buffer; + HBBuffer * fRawBuffer; + HBList * fRawBufferList; mpeg2dec_t * fHandle; bool fLateField; }; diff --git a/core/Mpeg4Encoder.cpp b/core/Mpeg4Encoder.cpp index 42fb38b9e..4ef0a4c3f 100644 --- a/core/Mpeg4Encoder.cpp +++ b/core/Mpeg4Encoder.cpp @@ -1,4 +1,4 @@ -/* $Id: Mpeg4Encoder.cpp,v 1.15 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg4Encoder.cpp,v 1.23 2003/10/09 13:24:48 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -11,49 +11,97 @@ #include <ffmpeg/avcodec.h> HBMpeg4Encoder::HBMpeg4Encoder( HBManager * manager, HBTitle * title ) - : HBThread( "mpeg4encoder" ) { fManager = manager; fTitle = title; + + fLock = new HBLock(); + fUsed = false; + + fPass = 42; + fMpeg4Buffer = NULL; + fFile = NULL; + fFrame = avcodec_alloc_frame(); + fLog = NULL; } -void HBMpeg4Encoder::DoWork() +bool HBMpeg4Encoder::Work() { - if( !( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) ) + if( !Lock() ) { - return; + return false; } - fPass = fResizedBuffer->fPass; - Init(); + bool didSomething = false; - do + for( ;; ) { - while( fSuspend ) + if( fMpeg4Buffer ) { - Snooze( 10000 ); + if( fTitle->fMpeg4Fifo->Push( fMpeg4Buffer ) ) + { + fMpeg4Buffer = NULL; + } + else + { + break; + } + } + + if( !( fResizedBuffer = fTitle->fResizedFifo->Pop() ) ) + { + break; } if( fResizedBuffer->fPass != fPass ) { - Close(); fPass = fResizedBuffer->fPass; Init(); } fManager->SetPosition( fResizedBuffer->fPosition ); EncodeBuffer(); + + didSomething = true; + } + + Unlock(); + return didSomething; +} + +bool HBMpeg4Encoder::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; } - while( ( fResizedBuffer = Pop( fTitle->fResizedFifo ) ) ); + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBMpeg4Encoder::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } void HBMpeg4Encoder::Init() { + /* Clean up if needed */ + if( fFile ) + { + fclose( fFile ); + } + AVCodec * codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); if( !codec ) { Log( "HBMpeg4Encoder: avcodec_find_encoder() failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_MPEG4_INIT ); return; } @@ -94,19 +142,9 @@ void HBMpeg4Encoder::Init() if( avcodec_open( fContext, codec ) < 0 ) { Log( "HBMpeg4Encoder: avcodec_open() failed" ); - fManager->Error(); + fManager->Error( HB_ERROR_MPEG4_INIT ); return; } - - fFrame = avcodec_alloc_frame(); -} - -void HBMpeg4Encoder::Close() -{ - if( fPass == 1 ) - { - fclose( fFile ); - } } void HBMpeg4Encoder::EncodeBuffer() @@ -120,31 +158,27 @@ void HBMpeg4Encoder::EncodeBuffer() fFrame->linesize[1] = fTitle->fOutWidth / 2; fFrame->linesize[2] = fTitle->fOutWidth / 2; - HBBuffer * mpeg4Buffer; - mpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth * + fMpeg4Buffer = 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; + fMpeg4Buffer->fPosition = fResizedBuffer->fPosition; + fMpeg4Buffer->fSize = + avcodec_encode_video( fContext, fMpeg4Buffer->fData, + fMpeg4Buffer->fAllocSize, fFrame ); + fMpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 ); - if( fPass == 1 ) + if( fResizedBuffer->fPass == 1 ) { if( fContext->stats_out ) { fprintf( fFile, "%s", fContext->stats_out ); } - delete mpeg4Buffer; - } - else - { - /* Mux it */ - Push( fTitle->fMpeg4Fifo, mpeg4Buffer ); + delete fMpeg4Buffer; + fMpeg4Buffer = NULL; } + + delete fResizedBuffer; + fResizedBuffer = NULL; } diff --git a/core/Mpeg4Encoder.h b/core/Mpeg4Encoder.h index 1bdb29434..3d20f315a 100644 --- a/core/Mpeg4Encoder.h +++ b/core/Mpeg4Encoder.h @@ -1,4 +1,4 @@ -/* $Id: Mpeg4Encoder.h,v 1.8 2003/09/30 14:38:15 titer Exp $ +/* $Id: Mpeg4Encoder.h,v 1.11 2003/10/08 11:56:40 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,29 +8,34 @@ #define HB_MPEG4_ENCODER_H #include "Common.h" -#include "Thread.h" -class HBMpeg4Encoder : public HBThread +class HBMpeg4Encoder { public: HBMpeg4Encoder( HBManager * manager, HBTitle * title ); + bool Work(); private: - void DoWork(); + bool Lock(); + void Unlock(); + void Init(); - void Close(); void EncodeBuffer(); HBManager * fManager; HBTitle * fTitle; + HBLock * fLock; + bool fUsed; + uint32_t fPass; HBBuffer * fResizedBuffer; AVCodecContext * fContext; AVFrame * fFrame; FILE * fFile; char * fLog; + HBBuffer * fMpeg4Buffer; }; #endif diff --git a/core/MpegDemux.cpp b/core/MpegDemux.cpp index d3fd6b089..c01647a3a 100644 --- a/core/MpegDemux.cpp +++ b/core/MpegDemux.cpp @@ -1,4 +1,4 @@ -/* $Id: MpegDemux.cpp,v 1.10 2003/10/04 12:12:48 titer Exp $ +/* $Id: MpegDemux.cpp,v 1.18 2003/10/13 15:14:01 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -14,146 +14,176 @@ extern "C" { HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitle * title, HBAudio * audio1, HBAudio * audio2 ) - : HBThread( "mpegdemux" ) { - fManager = manager; - fTitle = title; - fAudio1 = audio1; - fAudio2 = audio2; + fManager = manager; + fTitle = title; + fAudio1 = audio1; + fAudio2 = audio2; - fPSBuffer = NULL; - fESBuffer = NULL; - fESBufferList = NULL; + fLock = new HBLock(); + fUsed = false; + + fPSBuffer = NULL; + fESBuffer = NULL; + fESBufferList = NULL; fFirstVideoPTS = -1; fFirstAudio1PTS = -1; fFirstAudio2PTS = -1; } -void HBMpegDemux::DoWork() +HBMpegDemux::~HBMpegDemux() { - for( ;; ) + /* Free memory */ + if( fESBufferList ) { - while( fSuspend ) - { - Snooze( 10000 ); - } - - /* Get a PS packet */ - if( !( fPSBuffer = Pop( fTitle->fPSFifo ) ) ) + while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) ) { - break; + fESBufferList->RemoveItem( fESBuffer ); + delete fESBuffer; } + } + delete fLock; +} - /* Get the ES data in it */ - PStoES( fPSBuffer, &fESBufferList ); - - if( !fESBufferList ) - { - continue; - } +bool HBMpegDemux::Work() +{ + if( !Lock() ) + { + return false; + } + + bool didSomething = false; - while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) ) + for( ;; ) + { + /* If we have buffers waiting, try to push them */ + if( fESBufferList ) { - fESBufferList->RemoveItem( fESBuffer ); - - if( fESBuffer->fPass == 1 && fESBuffer->fStreamId != 0xE0 ) + for( uint32_t i = 0; i < fESBufferList->CountItems(); ) { - delete fESBuffer; - continue; - } + fESBuffer = (HBBuffer*) fESBufferList->ItemAt( i ); + + if( fESBuffer->fPass == 1 && fESBuffer->fStreamId != 0xE0 ) + { + fESBufferList->RemoveItem( fESBuffer ); + delete fESBuffer; + continue; + } - /* Look for a decoder for this ES */ - if( fESBuffer->fStreamId == 0xE0 ) - { - if( fFirstVideoPTS < 0 ) + /* Look for a decoder for this ES */ + + if( fESBuffer->fStreamId == 0xE0 ) { - fFirstVideoPTS = fESBuffer->fPTS; + if( fFirstVideoPTS < 0 ) + { + fFirstVideoPTS = fESBuffer->fPTS; + Log( "HBMpegDemux: got first 0xE0 packet (%lld)", + fFirstVideoPTS ); + } + if( fTitle->fMpeg2Fifo->Push( fESBuffer ) ) + { + fESBufferList->RemoveItem( fESBuffer ); + } + else + { + i++; + } } - Push( fTitle->fMpeg2Fifo, fESBuffer ); - } - 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 ) + else if( fAudio1 && + fESBuffer->fStreamId == fAudio1->fId ) { - fFirstAudio1PTS = fESBuffer->fPTS; + if( fFirstAudio1PTS < 0 ) + { + fFirstAudio1PTS = fESBuffer->fPTS; + Log( "HBMpegDemux: got first 0x%x packet (%lld)", + fAudio1->fId, fFirstAudio1PTS ); - if( fFirstAudio1PTS > fFirstVideoPTS ) + fAudio1->fDelay = + ( fFirstAudio1PTS - fFirstVideoPTS ) / 90; + } + if( fAudio1->fAc3Fifo->Push( fESBuffer ) ) + { + fESBufferList->RemoveItem( fESBuffer ); + } + else { - Log( "HBMpegDemux::DoWork() : audio track %x " - "is late (%lld)", fAudio1->fId, - fFirstAudio1PTS - fFirstVideoPTS ); - InsertSilence( fFirstAudio1PTS - fFirstVideoPTS, - fAudio1->fAc3Fifo, - fESBuffer ); + i++; } } - Push( fAudio1->fAc3Fifo, fESBuffer ); - } - else if( fAudio2 && - fESBuffer->fStreamId == fAudio2->fId ) - { - if( fFirstAudio2PTS < 0 ) + else if( fAudio2 && + fESBuffer->fStreamId == fAudio2->fId ) { - fFirstAudio2PTS = fESBuffer->fPTS; + if( fFirstAudio2PTS < 0 ) + { + fFirstAudio2PTS = fESBuffer->fPTS; + Log( "HBMpegDemux: got first 0x%x packet (%lld)", + fAudio2->fId, fFirstAudio2PTS ); - if( fFirstAudio2PTS > fFirstVideoPTS ) + fAudio2->fDelay = + ( fFirstAudio2PTS - fFirstVideoPTS ) / 90; + } + if( fAudio2->fAc3Fifo->Push( fESBuffer ) ) { - Log( "HBMpegDemux::DoWork() : audio track %x " - "is late (%lld)", fAudio2->fId, - fFirstAudio2PTS - fFirstVideoPTS ); - InsertSilence( fFirstAudio2PTS - fFirstVideoPTS, - fAudio2->fAc3Fifo, - fESBuffer ); + fESBufferList->RemoveItem( fESBuffer ); } + else + { + i++; + } + } + else + { + fESBufferList->RemoveItem( fESBuffer ); + delete fESBuffer; } - Push( fAudio2->fAc3Fifo, fESBuffer ); + } + + if( !fESBufferList->CountItems() ) + { + delete fESBufferList; + fESBufferList = NULL; } else { - delete fESBuffer; + break; } } - delete fESBufferList; - } -} -void HBMpegDemux::InsertSilence( int64_t time, HBFifo * fifo, - HBBuffer * buffer ) -{ - int flags = 0; - int sampleRate = 0; - int bitrate = 0; - int frameSize = a52_syncinfo( buffer->fData, &flags, - &sampleRate, &bitrate ); - - if( !frameSize ) - { - Log( "HBMpegDemux::InsertSilence() : a52_syncinfo() failed" ); - return; - } + /* Get a PS packet */ + if( !( fPSBuffer = fTitle->fPSFifo->Pop() ) ) + { + break; + } - uint32_t frames = ( ( sampleRate * time / 90000 ) + ( 3 * 256 ) ) - / ( 6 * 256 ); + /* Get the ES data in it */ + PStoES( fPSBuffer, &fESBufferList ); - if( !frames ) - { - return; + didSomething = true; } - Log( "HBMpegDemux::InsertSilence() : adding %d frames", frames ); + Unlock(); + return didSomething; +} - HBBuffer * buffer2; - for( uint32_t i = 0; i < frames; i++ ) +bool HBMpegDemux::Lock() +{ + fLock->Lock(); + if( fUsed ) { - buffer2 = new HBBuffer( frameSize ); - buffer2->fPosition = buffer->fPosition; - memcpy( buffer2->fData, buffer->fData, frameSize ); - Push( fifo, buffer2 ); - } + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBMpegDemux::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList ) diff --git a/core/MpegDemux.h b/core/MpegDemux.h index ef5b1b3d9..187a08de9 100644 --- a/core/MpegDemux.h +++ b/core/MpegDemux.h @@ -1,4 +1,4 @@ -/* $Id: MpegDemux.h,v 1.6 2003/10/04 12:12:48 titer Exp $ +/* $Id: MpegDemux.h,v 1.11 2003/10/09 13:24:48 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,26 +8,29 @@ #define HB_MPEG_DEMUX_H #include "Common.h" -#include "Thread.h" bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList ); -class HBMpegDemux : public HBThread +class HBMpegDemux { public: - HBMpegDemux( HBManager * manager, HBTitle * title, - HBAudio * audio1, HBAudio * audio2 ); + HBMpegDemux( HBManager * manager, HBTitle * title, + HBAudio * audio1, HBAudio * audio2 ); + ~HBMpegDemux(); + bool Work(); private: - void DoWork(); - void InsertSilence( int64_t time, HBFifo * fifo, - HBBuffer * buffer ); + bool Lock(); + void Unlock(); HBManager * fManager; HBTitle * fTitle; HBAudio * fAudio1; HBAudio * fAudio2; + HBLock * fLock; + bool fUsed; + HBBuffer * fPSBuffer; HBBuffer * fESBuffer; HBList * fESBufferList; diff --git a/core/Resizer.cpp b/core/Resizer.cpp index e3cae3986..0b9c794db 100644 --- a/core/Resizer.cpp +++ b/core/Resizer.cpp @@ -1,4 +1,4 @@ -/* $Id: Resizer.cpp,v 1.3 2003/09/30 14:38:15 titer Exp $ +/* $Id: Resizer.cpp,v 1.8 2003/10/09 13:24:48 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -11,79 +11,131 @@ #include <ffmpeg/avcodec.h> HBResizer::HBResizer( HBManager * manager, HBTitle * title ) - : HBThread( "resizer" ) { - fManager = manager; - fTitle = title; -} + fManager = manager; + fTitle = title; + + /* Lock */ + fLock = new HBLock(); + fUsed = false; -void HBResizer::DoWork() -{ /* Init libavcodec */ - ImgReSampleContext * resampleContext = + fResampleContext = 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, + fRawBuffer = NULL; + fDeinterlacedBuffer = new HBBuffer( 3 * fTitle->fInWidth * + fTitle->fInHeight / 2 ); + fResizedBuffer = NULL; + fRawPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); + fDeinterlacedPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); + fResizedPicture = (AVPicture*) malloc( sizeof( AVPicture ) ); + + avpicture_fill( fDeinterlacedPicture, fDeinterlacedBuffer->fData, PIX_FMT_YUV420P, fTitle->fInWidth, fTitle->fInHeight ); +} + +HBResizer::~HBResizer() +{ + /* Free memory */ + free( fResizedPicture ); + free( fDeinterlacedPicture ); + free( fRawPicture ); + if( fResizedBuffer ) delete fResizedBuffer; + delete fDeinterlacedBuffer; + img_resample_close( fResampleContext ); + delete fLock; +} +bool HBResizer::Work() +{ + if( !Lock() ) + { + return false; + } + + bool didSomething = false; + for( ;; ) { - while( fSuspend ) + /* Push the latest resized buffer */ + if( fResizedBuffer ) { - Snooze( 10000 ); + if( fTitle->fResizedFifo->Push( fResizedBuffer ) ) + { + fResizedBuffer = NULL; + } + else + { + break; + } } - - if( !( rawBuffer = Pop( fTitle->fRawFifo ) ) ) + + /* Get a new raw picture */ + if( !( fRawBuffer = fTitle->fRawFifo->Pop() ) ) { break; } - avpicture_fill( &rawPicture, rawBuffer->fData, + /* Do the job */ + avpicture_fill( fRawPicture, fRawBuffer->fData, PIX_FMT_YUV420P, fTitle->fInWidth, fTitle->fInHeight ); - resizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth * + fResizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth * fTitle->fOutHeight / 2 ); - resizedBuffer->fPosition = rawBuffer->fPosition; - resizedBuffer->fPass = rawBuffer->fPass; - avpicture_fill( &resizedPicture, resizedBuffer->fData, + fResizedBuffer->fPosition = fRawBuffer->fPosition; + fResizedBuffer->fPass = fRawBuffer->fPass; + avpicture_fill( fResizedPicture, fResizedBuffer->fData, PIX_FMT_YUV420P, fTitle->fOutWidth, fTitle->fOutHeight ); - if( fTitle->fDeinterlace ) { - avpicture_deinterlace( &deinterlacedPicture, &rawPicture, + avpicture_deinterlace( fDeinterlacedPicture, fRawPicture, PIX_FMT_YUV420P, fTitle->fInWidth, fTitle->fInHeight ); - img_resample( resampleContext, &resizedPicture, - &deinterlacedPicture ); + img_resample( fResampleContext, fResizedPicture, + fDeinterlacedPicture ); } else { - img_resample( resampleContext, &resizedPicture, - &rawPicture ); + img_resample( fResampleContext, fResizedPicture, + fRawPicture ); } + delete fRawBuffer; + fRawBuffer = NULL; - Push( fTitle->fResizedFifo, resizedBuffer ); - delete rawBuffer; + didSomething = true; } - /* Free memory */ - delete deinterlacedBuffer; + Unlock(); + return didSomething; +} - /* Close libavcodec */ - img_resample_close( resampleContext ); +bool HBResizer::Lock() +{ + fLock->Lock(); + if( fUsed ) + { + fLock->Unlock(); + return false; + } + fUsed = true; + fLock->Unlock(); + return true; +} + +void HBResizer::Unlock() +{ + fLock->Lock(); + fUsed = false; + fLock->Unlock(); } diff --git a/core/Resizer.h b/core/Resizer.h index 1fdde85d3..f6d4a4568 100644 --- a/core/Resizer.h +++ b/core/Resizer.h @@ -1,4 +1,4 @@ -/* $Id: Resizer.h,v 1.2 2003/09/30 14:38:15 titer Exp $ +/* $Id: Resizer.h,v 1.5 2003/10/07 22:48:31 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -8,18 +8,31 @@ #define HB_RESIZER_H #include "Common.h" -#include "Thread.h" -class HBResizer : public HBThread +class HBResizer { public: HBResizer( HBManager * manager, HBTitle * title ); + ~HBResizer(); + bool Work(); private: - void DoWork(); - + bool Lock(); + void Unlock(); + HBManager * fManager; HBTitle * fTitle; + + HBLock * fLock; + bool fUsed; + + ImgReSampleContext * fResampleContext; + HBBuffer * fRawBuffer; + HBBuffer * fDeinterlacedBuffer; + HBBuffer * fResizedBuffer; + AVPicture * fRawPicture; + AVPicture * fDeinterlacedPicture; + AVPicture * fResizedPicture; }; #endif diff --git a/core/Scanner.cpp b/core/Scanner.cpp index 575b25573..44ff6be3a 100644 --- a/core/Scanner.cpp +++ b/core/Scanner.cpp @@ -1,4 +1,4 @@ -/* $Id: Scanner.cpp,v 1.18 2003/10/04 12:12:48 titer Exp $ +/* $Id: Scanner.cpp,v 1.23 2003/10/13 14:12:18 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -20,21 +20,23 @@ extern "C" { } HBScanner::HBScanner( HBManager * manager, char * device ) - : HBThread( "scanner" ) + : HBThread( "scanner", HB_NORMAL_PRIORITY ) { fManager = manager; fDevice = strdup( device ); + + Run(); } void HBScanner::DoWork() { - Log( "HBScanner::DoWork() : opening device %s", fDevice ); + Log( "HBScanner: opening device %s", fDevice ); dvdplay_ptr vmg; vmg = dvdplay_open( fDevice, NULL, NULL ); if( !vmg ) { - Log( "HBScanner::DoWork() : dvdplay_open() failed (%s)", + Log( "HBScanner: dvdplay_open() failed (%s)", fDevice ); fManager->ScanDone( NULL ); return; @@ -50,7 +52,7 @@ void HBScanner::DoWork() break; } - Log( "HBScanner::DoWork() : scanning title %d", i + 1 ); + Log( "HBScanner: scanning title %d", i + 1 ); fManager->Scanning( fDevice, i + 1 ); title = new HBTitle( fDevice, i + 1 ); @@ -61,12 +63,12 @@ void HBScanner::DoWork() } else { - Log( "HBScanner::DoWork() : ignoring title %d", i + 1 ); + Log( "HBScanner: ignoring title %d", i + 1 ); delete title; } } - Log( "HBScanner::DoWork() : closing device %s", fDevice ); + Log( "HBScanner: closing device %s", fDevice ); dvdplay_close( vmg ); fManager->ScanDone( titleList ); @@ -78,7 +80,7 @@ bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg ) /* Length */ title->fLength = dvdplay_title_time( vmg ); - Log( "HBScanner::ScanTitle() : title length is %lld seconds", + Log( "HBScanner::ScanTitle: title length is %lld seconds", title->fLength ); /* Discard titles under 10 seconds */ @@ -101,20 +103,46 @@ bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg ) } int id = dvdplay_audio_id( vmg, i ); - if( id > 0 ) + + if( id < 1 ) { - if( ( id & 0xFF ) != 0xBD ) + continue; + } + + if( ( id & 0xFF ) != 0xBD ) + { + Log( "HBScanner::ScanTitle: non-AC3 audio track " + "detected, ignoring" ); + continue; + } + + /* Check if we don't already found an track with the same id */ + audio = NULL; + for( uint32_t j = 0; j < title->fAudioList->CountItems(); j++ ) + { + audio = (HBAudio*) title->fAudioList->ItemAt( j ); + if( (uint32_t) id == audio->fId ) + { + break; + } + else { - Log( "HBScanner::ScanTitle() : non-AC3 audio track " - "detected, ignoring" ); - continue; + audio = NULL; } - 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 ); } + + if( audio ) + { + Log( "HBScanner::ScanTitle: discarding duplicate track %x", + id ); + 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 */ @@ -206,7 +234,7 @@ bool HBScanner::DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i ) if( dvdplay_read( vmg, psBuffer->fData, 1 ) != 1 || !PStoES( psBuffer, &esBufferList ) ) { - Log( "HBScanner::DecodeFrame : failed to get " + Log( "HBScanner::DecodeFrame: failed to get " "a valid PS packet" ); mpeg2_close( handle ); fclose( file ); diff --git a/core/Thread.cpp b/core/Thread.cpp index 43f058cad..8f7e6c971 100644 --- a/core/Thread.cpp +++ b/core/Thread.cpp @@ -1,4 +1,4 @@ -/* $Id: Thread.cpp,v 1.19 2003/10/01 21:17:17 titer Exp $ +/* $Id: Thread.cpp,v 1.23 2003/10/09 23:33:36 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -34,61 +34,35 @@ HBThread::~HBThread() pthread_join( fThread, NULL ); #endif - Log( "Thread %d stopped (\"%s\")", fThread, fName ); + Log( "HBThread: thread %d stopped (\"%s\")", fThread, fName ); free( fName ); } -void HBThread::Run() +void HBThread::Suspend() { -#if defined( SYS_BEOS ) - fThread = spawn_thread( (int32 (*)(void *)) ThreadFunc, - fName, fPriority, this ); - resume_thread( fThread ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_create( &fThread, NULL, - (void * (*)(void *)) ThreadFunc, this ); -#if 0 -#if defined( SYS_MACOSX ) - int policy; - struct sched_param param; - memset( ¶m, 0, sizeof( struct sched_param ) ); - if( fPriority < 0 ) - { - param.sched_priority = (-1) * fPriority; - policy = SCHED_OTHER; - } - else - { - param.sched_priority = fPriority; - policy = SCHED_RR; - } - if ( pthread_setschedparam( fThread, policy, ¶m ) ) - { - Log( "HBThread::Run : couldn't set thread priority" ); - } -#endif -#endif -#endif - - Log( "Thread %d started (\"%s\")", fThread, fName ); + fSuspend = true; } -void HBThread::Stop() +void HBThread::Resume() { - Log( "Stopping thread %d (\"%s\")", fThread, fName ); - - fDie = true; fSuspend = false; } -void HBThread::Suspend() +int HBThread::GetPid() { - fSuspend = true; + return fPid; } -void HBThread::Resume() +void HBThread::Run() { - fSuspend = false; +#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 ); +#endif } bool HBThread::Push( HBFifo * fifo, HBBuffer * buffer ) @@ -126,6 +100,21 @@ HBBuffer * HBThread::Pop( HBFifo * fifo ) void HBThread::ThreadFunc( HBThread * _this ) { +#if defined( SYS_MACOSX ) + struct sched_param param; + memset( ¶m, 0, sizeof( struct sched_param ) ); + param.sched_priority = _this->fPriority; + if ( pthread_setschedparam( _this->fThread, SCHED_OTHER, ¶m ) ) + { + Log( "HBThread: couldn't set thread priority" ); + } +#endif + + _this->fPid = (int) getpid(); + + Log( "HBThread: thread %d started (\"%s\")", + _this->fThread, _this->fName ); + _this->DoWork(); } diff --git a/core/Thread.h b/core/Thread.h index 6afd59f53..0a09fabc9 100644 --- a/core/Thread.h +++ b/core/Thread.h @@ -1,4 +1,4 @@ -/* $Id: Thread.h,v 1.16 2003/10/01 21:17:17 titer Exp $ +/* $Id: Thread.h,v 1.19 2003/10/09 16:03:51 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -13,8 +13,8 @@ # 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 */ +# define HB_LOW_PRIORITY 0 +# define HB_NORMAL_PRIORITY 31 #elif defined( SYS_LINUX ) /* Actually unused */ # define HB_LOW_PRIORITY 0 @@ -27,12 +27,12 @@ class HBThread HBThread( char * name, int priority = HB_LOW_PRIORITY ); virtual ~HBThread(); - void Run(); - void Stop(); void Suspend(); void Resume(); + int GetPid(); protected: + void Run(); bool Push( HBFifo * fifo, HBBuffer * buffer ); HBBuffer * Pop( HBFifo * fifo ); @@ -51,6 +51,7 @@ class HBThread #elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) pthread_t fThread; #endif + int fPid; }; #if defined( SYS_BEOS ) diff --git a/core/Worker.cpp b/core/Worker.cpp new file mode 100644 index 000000000..5f1352026 --- /dev/null +++ b/core/Worker.cpp @@ -0,0 +1,150 @@ +/* $Id: Worker.cpp,v 1.9 2003/10/13 17:59: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 "Ac3Decoder.h" +#include "Mp3Encoder.h" +#include "Mpeg2Decoder.h" +#include "Mpeg4Encoder.h" +#include "MpegDemux.h" +#include "Resizer.h" +#include "Worker.h" + +HBWorker::HBWorker( HBTitle * title, HBAudio * audio1, + HBAudio * audio2 ) + : HBThread( "worker") +{ + fTitle = title; + fAudio1 = audio1; + fAudio2 = audio2; + + Run(); +} + +void HBWorker::DoWork() +{ + bool didSomething; + uint64_t mpegDemux = 0; + uint64_t mpeg2Decoder = 0; + uint64_t resizer = 0; + uint64_t mpeg4Encoder = 0; + uint64_t ac3Decoder1 = 0; + uint64_t mp3Encoder1 = 0; + uint64_t ac3Decoder2 = 0; + uint64_t mp3Encoder2 = 0; + uint64_t tmpDate; + + while( !fDie ) + { + didSomething = false; + + tmpDate = GetDate(); + if( fTitle->fMpegDemux->Work() ) + { + mpegDemux += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fTitle->fMpeg2Decoder->Work() ) + { + mpeg2Decoder += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fTitle->fResizer->Work() ) + { + resizer += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fTitle->fMpeg4Encoder->Work() ) + { + mpeg4Encoder += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + if( fAudio1 ) + { + tmpDate = GetDate(); + if( fAudio1->fAc3Decoder->Work() ) + { + ac3Decoder1 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fAudio1->fMp3Encoder->Work() ) + { + mp3Encoder1 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + } + + if( fAudio2 ) + { + tmpDate = GetDate(); + if( fAudio2->fAc3Decoder->Work() ) + { + ac3Decoder2 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + + tmpDate = GetDate(); + if( fAudio2->fMp3Encoder->Work() ) + { + mp3Encoder2 += ( GetDate() - tmpDate ); + didSomething = true; + } + + if( fDie ) break; + } + + if( !didSomething ) + { + Snooze( 10000 ); + } + + while( fSuspend ) + { + Snooze( 10000 ); + } + } + + tmpDate = mpegDemux + mpeg2Decoder + resizer + mpeg4Encoder + + ac3Decoder1 + mp3Encoder1 + ac3Decoder2 + mp3Encoder2; + Log( "HBWorker stopped. CPU utilization:" ); + Log( "- MPEG demuxer: %.2f %%", 100 * (float) mpegDemux / tmpDate ); + Log( "- MPEG-2 decoder: %.2f %%", 100 * (float) mpeg2Decoder / tmpDate ); + Log( "- Resizer: %.2f %%", 100 * (float) resizer / tmpDate ); + Log( "- MPEG-4 encoder: %.2f %%", 100 * (float) mpeg4Encoder / tmpDate ); + if( fAudio1 ) + { + Log( "- AC3 decoder 1: %.2f %%", 100 * (float) ac3Decoder1 / tmpDate ); + Log( "- MP3 encoder 1: %.2f %%", 100 * (float) mp3Encoder1 / tmpDate ); + } + if( fAudio2 ) + { + Log( "- AC3 decoder 2: %.2f %%", 100 * (float) ac3Decoder2 / tmpDate ); + Log( "- MP3 encoder 2: %.2f %%", 100 * (float) mp3Encoder2 / tmpDate ); + } +} + diff --git a/core/Worker.h b/core/Worker.h new file mode 100644 index 000000000..d2d0324d8 --- /dev/null +++ b/core/Worker.h @@ -0,0 +1,27 @@ +/* $Id: Worker.h,v 1.1 2003/10/07 17:40:06 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_WORKER_H +#define HB_WORKER_H + +#include "Common.h" +#include "Thread.h" + +class HBWorker : public HBThread +{ + public: + HBWorker( HBTitle * title, HBAudio * audio1, + HBAudio * audio2 ); + + private: + void DoWork(); + + HBTitle * fTitle; + HBAudio * fAudio1; + HBAudio * fAudio2; +}; + +#endif diff --git a/macosx/HBController.h b/macosx/Controller.h index 2e3339c74..4759a1d5b 100644 --- a/macosx/HBController.h +++ b/macosx/Controller.h @@ -1,4 +1,4 @@ -/* $Id: HBController.h,v 1.19 2003/10/06 21:13:45 titer Exp $ +/* $Id: Controller.h,v 1.6 2003/10/13 23:09:56 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -6,14 +6,19 @@ #include <Cocoa/Cocoa.h> -#include "Manager.h" +#include "Common.h" #include "PictureGLView.h" +#include "TargetSizeField.h" @interface HBController : NSObject { + bool fDie; + IBOutlet NSWindow * fWindow; + /* Scan view */ + uint64_t fLastDVDDetection; IBOutlet NSView * fScanView; IBOutlet NSMatrix * fScanMatrix; IBOutlet NSPopUpButton * fDVDPopUp; @@ -23,25 +28,44 @@ IBOutlet NSProgressIndicator * fScanProgress; IBOutlet NSButton * fScanButton; + IBOutlet NSView * fTempView; + + /* Rip view */ IBOutlet NSView * fRipView; + + /* Video box */ IBOutlet NSPopUpButton * fTitlePopUp; - IBOutlet NSPopUpButton * fAudioPopUp; - IBOutlet NSTextField * fVideoField; - IBOutlet NSStepper * fVideoStepper; - IBOutlet NSTextField * fAudioField; - IBOutlet NSStepper * fAudioStepper; + IBOutlet NSPopUpButton * fVideoCodecPopUp; + IBOutlet NSMatrix * fVideoMatrix; + IBOutlet NSTextField * fCustomBitrateField; + IBOutlet HBTargetSizeField * fTargetSizeField; IBOutlet NSButton * fTwoPassCheck; IBOutlet NSButton * fCropButton; + + /* Audio box */ + IBOutlet NSPopUpButton * fLanguagePopUp; + IBOutlet NSPopUpButton * fSecondaryLanguagePopUp; + IBOutlet NSPopUpButton * fAudioCodecPopUp; + IBOutlet NSPopUpButton * fAudioBitratePopUp; + + /* Destination box */ + IBOutlet NSPopUpButton * fFileFormatPopUp; IBOutlet NSTextField * fFileField; - IBOutlet NSButton * fRipBrowseButton; + IBOutlet NSButton * fFileBrowseButton; + + /* Bottom */ IBOutlet NSTextField * fRipStatusField; + IBOutlet NSTextField * fRipInfoField; IBOutlet NSProgressIndicator * fRipProgress; IBOutlet NSButton * fSuspendButton; IBOutlet NSButton * fRipButton; + + /* "Done" alert panel */ IBOutlet NSPanel * fDonePanel; + /* Crop & resize panel */ IBOutlet NSPanel * fPicturePanel; - IBOutlet PictureGLView * fPictureGLView; + IBOutlet HBPictureGLView * fPictureGLView; IBOutlet NSTextField * fWidthField; IBOutlet NSStepper * fWidthStepper; IBOutlet NSButton * fDeinterlaceCheck; @@ -56,22 +80,28 @@ IBOutlet NSTextField * fInfoField; int fPicture; - IBOutlet NSView * fBlankView; HBManager * fManager; HBList * fTitleList; } +- (IBAction) ScanMatrixChanged: (id) sender; - (IBAction) BrowseDVD: (id) sender; - (void) BrowseDVDDone: (NSOpenPanel *) sheet returnCode: (int) returnCode contextInfo: (void *) contextInfo; - (IBAction) Scan: (id) sender; +- (IBAction) TitlePopUpChanged: (id) sender; +- (IBAction) VideoMatrixChanged: (id) sender; +- (IBAction) AudioPopUpChanged: (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; +- (void) OverwriteAlertDone: (NSWindow *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo; +- (void) _Rip; - (IBAction) Cancel: (id) sender; - (IBAction) Suspend: (id) sender; - (IBAction) Resume: (id) sender; @@ -82,7 +112,5 @@ - (void) UpdateIntf: (NSTimer *) timer; - (void) DetectDrives; -- (void) ScanEnableIntf: (id) sender; -- (void) UpdatePopUp: (id) sender; @end diff --git a/macosx/HBController.mm b/macosx/Controller.mm index f46d0221a..402d721fa 100644 --- a/macosx/HBController.mm +++ b/macosx/Controller.mm @@ -1,4 +1,4 @@ -/* $Id: HBController.mm,v 1.24 2003/10/06 21:13:45 titer Exp $ +/* $Id: Controller.mm,v 1.10 2003/10/13 23:09:56 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -10,7 +10,7 @@ #include <IOKit/storage/IOMedia.h> #include <IOKit/storage/IODVDMedia.h> -#include "HBController.h" +#include "Controller.h" #include "Manager.h" @implementation HBController @@ -21,15 +21,17 @@ fManager = new HBManager( true ); /* Update the GUI every 1/10 sec */ + fDie = false; [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector: @selector( UpdateIntf: ) - userInfo: nil repeats: FALSE]; + userInfo: nil repeats: YES]; } - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *) app { /* Clean up */ + fDie = true; delete fManager; return NSTerminateNow; @@ -37,17 +39,21 @@ - (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]; + [fDVDPopUp removeAllItems]; [fScanProgress setStyle: NSProgressIndicatorSpinningStyle]; [fScanProgress setDisplayedWhenStopped: NO]; - [fRipProgress setIndeterminate: NO]; - [fTitlePopUp removeAllItems]; - [fAudioPopUp removeAllItems]; + [fAudioBitratePopUp removeAllItems]; + [fAudioBitratePopUp addItemWithTitle: @"32"]; + [fAudioBitratePopUp addItemWithTitle: @"64"]; + [fAudioBitratePopUp addItemWithTitle: @"96"]; + [fAudioBitratePopUp addItemWithTitle: @"128"]; + [fAudioBitratePopUp addItemWithTitle: @"160"]; + [fAudioBitratePopUp addItemWithTitle: @"192"]; + [fAudioBitratePopUp addItemWithTitle: @"224"]; + [fAudioBitratePopUp addItemWithTitle: @"256"]; + [fAudioBitratePopUp addItemWithTitle: @"288"]; + [fAudioBitratePopUp addItemWithTitle: @"320"]; + [fAudioBitratePopUp selectItemWithTitle: @"128"]; char string[1024]; memset( string, 0, 1024 ); snprintf( string, 1024, "%s/Desktop/Movie.avi", getenv( "HOME" ) ); @@ -59,11 +65,9 @@ [fWindow center]; /* Detect DVD drives */ + fLastDVDDetection = GetDate(); [self DetectDrives]; - [self ScanEnableIntf: self]; - - /* Init a blank view, used in window resizing animation */ - fBlankView = [[NSView alloc] init]; + [self ScanMatrixChanged: self]; } - (BOOL) windowShouldClose: (id) sender @@ -98,6 +102,21 @@ } } +- (IBAction) VideoMatrixChanged: (id) sender; +{ + if( ![fVideoMatrix selectedRow] ) + { + [fCustomBitrateField setEnabled: YES]; + [fTargetSizeField setEnabled: NO]; + } + else + { + [fCustomBitrateField setEnabled: NO]; + [fTargetSizeField setEnabled: YES]; + [fTargetSizeField UpdateBitrate]; + } +} + - (IBAction) BrowseFile: (id) sender { /* Open a panel to let the user choose and update the text field */ @@ -188,15 +207,12 @@ /* XXX */ newSize.width = 762 /*fPicturePanelSize.width*/ + title->fOutWidthMax - 720; - newSize.height = 754 /*fPicturePanelSize.height*/ + + newSize.height = 740 /*fPicturePanelSize.height*/ + title->fOutHeightMax - 576; [fPicturePanel setContentSize: newSize]; - [NSApp beginSheet: fPicturePanel - modalForWindow: fWindow - modalDelegate: nil - didEndSelector: nil - contextInfo: nil]; + [NSApp beginSheet: fPicturePanel modalForWindow: fWindow + modalDelegate: nil didEndSelector: nil contextInfo: nil]; [NSApp runModalForWindow: fPicturePanel]; [NSApp endSheet: fPicturePanel]; [fPicturePanel orderOut: self]; @@ -216,19 +232,78 @@ return; } + if( [fCustomBitrateField intValue] < 256 ) + { + NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops", + nil, nil, fWindow, self, nil, nil, nil, + @"Video bitrate is too low !" ); + return; + } + if( [fCustomBitrateField intValue] > 8192 ) + { + NSBeginCriticalAlertSheet( @"Invalid video bitrate", @"Ooops", + nil, nil, fWindow, self, nil, nil, nil, + @"Video bitrate is too high !" ); + return; + } + if( [fLanguagePopUp indexOfSelectedItem] == + [fSecondaryLanguagePopUp indexOfSelectedItem] ) + { + NSBeginCriticalAlertSheet( @"Invalid secondary language", + @"Ooops", nil, nil, fWindow, self, nil, nil, nil, + @"Do you _really_ want to encode the same audio track twice?" ); + return; + } + + FILE * file; + if( ( file = fopen( [[fFileField stringValue] cString], "r" ) ) ) + { + fclose( file ); + NSBeginCriticalAlertSheet( @"File already exists", + @"Nooo", @"Yes, go ahead!", nil, fWindow, self, + @selector( OverwriteAlertDone:returnCode:contextInfo: ), + nil, nil, + [NSString stringWithFormat: @"Do you want to overwrite %s ?", + [[fFileField stringValue] cString]] ); + return; + } + + [self _Rip]; +} + +- (void) OverwriteAlertDone: (NSWindow *) sheet + returnCode: (int) returnCode contextInfo: (void *) contextInfo +{ + if( returnCode == NSAlertAlternateReturn ) + { + [self _Rip]; + } +} + +- (void) _Rip +{ /* Get the specified title & audio track(s) */ HBTitle * title = (HBTitle*) fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); - HBAudio * audio = (HBAudio*) - title->fAudioList->ItemAt( [fAudioPopUp indexOfSelectedItem] ); + HBAudio * audio1 = (HBAudio*) + title->fAudioList->ItemAt( [fLanguagePopUp indexOfSelectedItem] ); + HBAudio * audio2 = (HBAudio*) + title->fAudioList->ItemAt( [fSecondaryLanguagePopUp + indexOfSelectedItem] ); /* Use user settings */ - title->fBitrate = [fVideoStepper intValue]; - audio->fOutBitrate = [fAudioStepper intValue]; - title->fTwoPass = ( [fTwoPassCheck state] == NSOnState ); + title->fBitrate = [fCustomBitrateField intValue]; + title->fTwoPass = ( [fTwoPassCheck state] == NSOnState ); + audio1->fOutBitrate = [[fAudioBitratePopUp titleOfSelectedItem] + intValue]; + if( audio2 ) + { + audio2->fOutBitrate = + [[fAudioBitratePopUp titleOfSelectedItem] intValue]; + } /* Let libhb do the job */ - fManager->StartRip( title, audio, NULL, + fManager->StartRip( title, audio1, audio2, (char*) [[fFileField stringValue] cString] ); } @@ -303,6 +378,20 @@ - (void) UpdateIntf: (NSTimer *) timer { + if( fDie ) + { + [timer invalidate]; + return; + } + + /* Update DVD popup */ + if( [fWindow contentView] == fScanView && + GetDate() > fLastDVDDetection + 2000000 ) + { + [self DetectDrives]; + fLastDVDDetection = GetDate(); + } + /* Ask libhb about what's happening now */ if( fManager->NeedUpdate() ) { @@ -343,7 +432,7 @@ case HB_MODE_INVALID_VOLUME: { [fScanMatrix setEnabled: YES]; - [self ScanEnableIntf: self]; + [self ScanMatrixChanged: self]; [fScanProgress stopAnimation: self]; [fScanButton setEnabled: YES]; @@ -358,7 +447,7 @@ /* Show a temporary empty view while the window resizing animation */ - [fWindow setContentView: fBlankView ]; + [fWindow setContentView: fTempView ]; /* Actually resize it */ NSRect newFrame; @@ -376,6 +465,7 @@ [fWindow setContentView: fRipView ]; [fSuspendButton setEnabled: NO]; + [fTitlePopUp removeAllItems]; HBTitle * title; for( uint32_t i = 0; i < fTitleList->CountItems(); i++ ) { @@ -387,29 +477,31 @@ title->fLength % 60 ); [[fTitlePopUp menu] addItemWithTitle: [NSString stringWithCString: string] - action: @selector( UpdatePopUp: ) - keyEquivalent: @""]; + action: nil keyEquivalent: @""]; } - [self UpdatePopUp: self]; + [self TitlePopUpChanged: 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"]; + [fTitlePopUp setEnabled: NO]; + [fVideoCodecPopUp setEnabled: NO]; + [fVideoMatrix setEnabled: NO]; + [fCustomBitrateField setEnabled: NO]; + [fTargetSizeField setEnabled: NO]; + [fTwoPassCheck setEnabled: NO]; + [fCropButton setEnabled: NO]; + [fLanguagePopUp setEnabled: NO]; + [fSecondaryLanguagePopUp setEnabled: NO]; + [fAudioCodecPopUp setEnabled: NO]; + [fAudioBitratePopUp setEnabled: NO]; + [fFileFormatPopUp setEnabled: NO]; + [fFileBrowseButton setEnabled: NO]; + [fSuspendButton setEnabled: YES]; + [fSuspendButton setTitle: @"Suspend"]; + [fRipButton setTitle: @"Cancel"]; if( !status.fPosition ) { @@ -419,15 +511,22 @@ } else { - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "Encoding: %.2f %%, %.2f fps " - "(%02d:%02d:%02d remaining)", - 100 * status.fPosition, status.fFrameRate, + char string[1024]; + memset( string, 0, 1024 ); + sprintf( string, "Encoding: %.2f %%", + 100 * status.fPosition ); + [fRipStatusField setStringValue: + [NSString stringWithCString: string]]; + memset( string, 0, 1024 ); + sprintf( string, + "Speed: %.2f fps (%02d:%02d:%02d remaining)", + status.fFrameRate, status.fRemainingTime / 3600, ( status.fRemainingTime % 3600 ) / 60, status.fRemainingTime % 60 ); - [fRipStatusField setStringValue: + [fRipInfoField setStringValue: [NSString stringWithCString: string]]; + [fRipProgress setIndeterminate: NO]; [fRipProgress setDoubleValue: 100 * status.fPosition]; } @@ -438,10 +537,11 @@ case HB_MODE_SUSPENDED: { char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "Encoding: %.2f %%, %.2f fps (PAUSED)", - 100 * status.fPosition, status.fFrameRate) ; + sprintf( string, "Encoding: %.2f %% (PAUSED)", + 100 * status.fPosition ) ; [fRipStatusField setStringValue: [NSString stringWithCString: string]]; + [fRipInfoField setStringValue: @""]; [fRipProgress setDoubleValue: 100 * status.fPosition]; @@ -449,50 +549,91 @@ break; } + case HB_MODE_STOPPING: + [fRipStatusField setStringValue: @"Stopping..."]; + [fRipInfoField setStringValue: @""]; + [fRipProgress setIndeterminate: YES]; + [fRipProgress startAnimation: self];; + 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"]; + [fRipProgress setIndeterminate: NO]; if( status.fMode == HB_MODE_DONE ) { - [fRipStatusField setStringValue: @"Done." ]; [fRipProgress setDoubleValue: 100]; + [fRipStatusField setStringValue: @"Done." ]; NSBeep(); [NSApp requestUserAttention: NSInformationalRequest]; [NSApp beginSheet: fDonePanel - modalForWindow: fWindow - modalDelegate: nil - didEndSelector: nil - contextInfo: nil]; + 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]; + [fRipStatusField setStringValue: @"Canceled." ]; } else { - [fRipStatusField setStringValue: @"An error occured." ]; [fRipProgress setDoubleValue: 0]; + switch( status.fError ) + { + case HB_ERROR_A52_SYNC: + [fRipStatusField setStringValue: + @"An error occured (corrupted AC3 data)." ]; + break; + case HB_ERROR_AVI_WRITE: + [fRipStatusField setStringValue: + @"An error occured (could not write to file)." ]; + break; + case HB_ERROR_DVD_OPEN: + [fRipStatusField setStringValue: + @"An error occured (could not open device)." ]; + break; + case HB_ERROR_DVD_READ: + [fRipStatusField setStringValue: + @"An error occured (DVD read failed)." ]; + break; + case HB_ERROR_MP3_INIT: + [fRipStatusField setStringValue: + @"An error occured (could not init MP3 encoder)." ]; + break; + case HB_ERROR_MP3_ENCODE: + [fRipStatusField setStringValue: + @"An error occured (MP3 encoder failed)." ]; + break; + case HB_ERROR_MPEG4_INIT: + [fRipStatusField setStringValue: + @"An error occured (could not init MPEG4 encoder)." ]; + break; + } } + [fRipInfoField setStringValue: @""]; + + [fTitlePopUp setEnabled: YES]; + [fVideoCodecPopUp setEnabled: YES]; + [fVideoMatrix setEnabled: YES]; + [fTwoPassCheck setEnabled: YES]; + [fCropButton setEnabled: YES]; + [fLanguagePopUp setEnabled: YES]; + [fSecondaryLanguagePopUp setEnabled: YES]; + [fAudioCodecPopUp setEnabled: YES]; + [fAudioBitratePopUp setEnabled: YES]; + [fFileFormatPopUp setEnabled: YES]; + [fFileBrowseButton setEnabled: YES]; + [fSuspendButton setEnabled: NO]; + [fSuspendButton setTitle: @"Suspend"]; + [fRipButton setTitle: @"Rip"]; + + [self VideoMatrixChanged: self]; + /* Warn the finder to update itself */ [[NSWorkspace sharedWorkspace] noteFileSystemChanged: [fFileField stringValue]]; @@ -502,18 +643,10 @@ 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; @@ -544,6 +677,9 @@ return; } + NSMutableArray * drivesList; + drivesList = [NSMutableArray arrayWithCapacity: 1]; + next_media = IOIteratorNext( media_iterator ); if( next_media != NULL ) { @@ -571,9 +707,8 @@ sizeof(psz_buf) - dev_path_length, kCFStringEncodingASCII ) ) { - [[fDVDPopUp menu] addItemWithTitle: - [NSString stringWithCString: psz_buf] - action: nil keyEquivalent: @""]; + [drivesList addObject: + [NSString stringWithCString: psz_buf]]; } CFRelease( str_bsd_path ); @@ -584,9 +719,37 @@ } IOObjectRelease( media_iterator ); + + /* Refresh only if a change occured */ + if( [drivesList count] == (unsigned) [fDVDPopUp numberOfItems] ) + { + bool isSame = true; + for( unsigned i = 0; i < [drivesList count]; i++ ) + { + if( ![[drivesList objectAtIndex: i] isEqualToString: + [fDVDPopUp itemTitleAtIndex: i]] ) + { + isSame = false; + break; + } + } + if( isSame ) + { + return; + } + } + + [fDVDPopUp removeAllItems]; + for( unsigned i = 0; i < [drivesList count]; i++ ) + { + [[fDVDPopUp menu] addItemWithTitle: + [drivesList objectAtIndex: i] action: nil + keyEquivalent: @""]; + } + [self ScanMatrixChanged: self]; } -- (void) ScanEnableIntf: (id) sender +- (IBAction) ScanMatrixChanged: (id) sender { if( ![fScanMatrix selectedRow] ) { @@ -604,12 +767,13 @@ } } -- (void) UpdatePopUp: (id) sender +- (IBAction) TitlePopUpChanged: (id) sender { HBTitle * title = (HBTitle*) fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); - [fAudioPopUp removeAllItems]; + [fLanguagePopUp removeAllItems]; + [fSecondaryLanguagePopUp removeAllItems]; HBAudio * audio; for( uint32_t i = 0; i < title->fAudioList->CountItems(); i++ ) @@ -618,9 +782,30 @@ /* We cannot use NSPopUpButton's addItemWithTitle because it checks for duplicate entries */ - [[fAudioPopUp menu] addItemWithTitle: + [[fLanguagePopUp menu] addItemWithTitle: [NSString stringWithCString: audio->fDescription] action: nil keyEquivalent: @""]; + [[fSecondaryLanguagePopUp menu] addItemWithTitle: + [NSString stringWithCString: audio->fDescription] + action: nil keyEquivalent: @""]; + } + [fSecondaryLanguagePopUp addItemWithTitle: @"None"]; + [fSecondaryLanguagePopUp selectItemWithTitle: @"None"]; + [fSecondaryLanguagePopUp setEnabled: + ( title->fAudioList->CountItems() > 1 )]; + + [fTargetSizeField SetHBTitle: title]; + if( [fVideoMatrix selectedRow] ) + { + [fTargetSizeField UpdateBitrate]; + } +} + +- (IBAction) AudioPopUpChanged: (id) sender +{ + if( [fVideoMatrix selectedRow] ) + { + [fTargetSizeField UpdateBitrate]; } } diff --git a/macosx/English.lproj/InfoPlist.strings b/macosx/English.lproj/InfoPlist.strings Binary files differindex ae4f04858..5ed7ca9e2 100644 --- a/macosx/English.lproj/InfoPlist.strings +++ b/macosx/English.lproj/InfoPlist.strings diff --git a/macosx/English.lproj/MainMenu.nib/classes.nib b/macosx/English.lproj/MainMenu.nib/classes.nib index df2438f40..38429950c 100644 --- a/macosx/English.lproj/MainMenu.nib/classes.nib +++ b/macosx/English.lproj/MainMenu.nib/classes.nib @@ -3,6 +3,7 @@ {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, { ACTIONS = { + AudioPopUpChanged = id; BrowseDVD = id; BrowseFile = id; Cancel = id; @@ -12,36 +13,39 @@ Resume = id; Rip = id; Scan = id; - ScanEnableIntf = id; + ScanMatrixChanged = id; ShowPicturePanel = id; Suspend = id; + TitlePopUpChanged = id; UpdatePicture = id; - UpdatePopUp = id; + VideoMatrixChanged = id; }; CLASS = HBController; LANGUAGE = ObjC; OUTLETS = { - fAudioField = NSTextField; - fAudioPopUp = NSPopUpButton; - fAudioStepper = NSStepper; - fBlankView = NSView; + fAudioBitratePopUp = NSPopUpButton; + fAudioCodecPopUp = NSPopUpButton; fBottomField = NSTextField; fBottomStepper = NSStepper; fCropButton = NSButton; + fCustomBitrateField = NSTextField; fDVDFolderField = NSTextField; fDVDPopUp = NSPopUpButton; fDeinterlaceCheck = NSButton; fDonePanel = NSPanel; + fFileBrowseButton = NSButton; fFileField = NSTextField; + fFileFormatPopUp = NSPopUpButton; fInfoField = NSTextField; + fLanguagePopUp = NSPopUpButton; fLeftField = NSTextField; fLeftStepper = NSStepper; - fPictureGLView = PictureGLView; + fPictureGLView = HBPictureGLView; fPicturePanel = NSPanel; fRightField = NSTextField; fRightStepper = NSStepper; - fRipBrowseButton = NSButton; fRipButton = NSButton; + fRipInfoField = NSTextField; fRipProgress = NSProgressIndicator; fRipStatusField = NSTextField; fRipView = NSView; @@ -51,19 +55,33 @@ fScanProgress = NSProgressIndicator; fScanStatusField = NSTextField; fScanView = NSView; + fSecondaryLanguagePopUp = NSPopUpButton; fSuspendButton = NSButton; + fTargetSizeField = HBTargetSizeField; + fTempView = NSView; fTitlePopUp = NSPopUpButton; fTopField = NSTextField; fTopStepper = NSStepper; fTwoPassCheck = NSButton; - fVideoField = NSTextField; - fVideoStepper = NSStepper; + fVideoCodecPopUp = NSPopUpButton; + fVideoMatrix = NSMatrix; fWidthField = NSTextField; fWidthStepper = NSStepper; fWindow = NSWindow; }; SUPERCLASS = NSObject; }, + {CLASS = HBPictureGLView; LANGUAGE = ObjC; SUPERCLASS = NSOpenGLView; }, + { + CLASS = HBTargetSizeField; + LANGUAGE = ObjC; + OUTLETS = { + fAudioBitratePopUp = NSPopUpButton; + fBitrateField = NSTextField; + fSecondaryLanguagePopUp = NSPopUpButton; + }; + SUPERCLASS = NSTextField; + }, {CLASS = PictureGLView; LANGUAGE = ObjC; SUPERCLASS = NSOpenGLView; } ); IBVersion = 1; diff --git a/macosx/English.lproj/MainMenu.nib/info.nib b/macosx/English.lproj/MainMenu.nib/info.nib index 0dbd97023..af41a1429 100644 --- a/macosx/English.lproj/MainMenu.nib/info.nib +++ b/macosx/English.lproj/MainMenu.nib/info.nib @@ -3,25 +3,29 @@ <plist version="1.0"> <dict> <key>IBDocumentLocation</key> - <string>109 136 381 380 0 0 1440 878 </string> + <string>29 16 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> + <key>556</key> + <string>510 480 420 244 0 0 1440 878 </string> + <key>583</key> + <string>648 516 144 171 0 0 1440 878 </string> + <key>589</key> + <string>510 282 420 586 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>583</integer> <integer>21</integer> + <integer>589</integer> + <integer>365</integer> <integer>434</integer> <integer>29</integer> + <integer>556</integer> </array> <key>IBSystem Version</key> <string>6R73</string> diff --git a/macosx/English.lproj/MainMenu.nib/objects.nib b/macosx/English.lproj/MainMenu.nib/objects.nib Binary files differindex a7849eb54..9fe323510 100644 --- a/macosx/English.lproj/MainMenu.nib/objects.nib +++ b/macosx/English.lproj/MainMenu.nib/objects.nib diff --git a/macosx/HandBrake.pbproj/project.pbxproj b/macosx/HandBrake.pbproj/project.pbxproj index b4ea5fef5..5f4045553 100644 --- a/macosx/HandBrake.pbproj/project.pbxproj +++ b/macosx/HandBrake.pbproj/project.pbxproj @@ -17,6 +17,8 @@ 4DF3C8CC052889CD00A80101, 4D85758E052B78E300C39CA9, 4D85758F052B78E300C39CA9, + 4D358C000534A91300D654EB, + 4D358C010534A91300D654EB, ); isa = PBXGroup; name = Classes; @@ -156,6 +158,7 @@ 29B97315FDCFA39411CA2CEA = { children = ( 29B97316FDCFA39411CA2CEA, + 4D358C040534AB8100D654EB, 4D929FEB0527903D00A80101, ); isa = PBXGroup; @@ -260,7 +263,7 @@ <key>CFBundleExecutable</key> <string>HandBrake</string> <key>CFBundleGetInfoString</key> - <string>HandBrake 0.3 - By Eric Petit <[email protected]></string> + <string>HandBrake 0.4 - By Eric Petit <[email protected]></string> <key>CFBundleIconFile</key> <string>HandBrake.icns</string> <key>CFBundleIdentifier</key> @@ -272,11 +275,11 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>0.3</string> + <string>0.4</string> <key>CFBundleSignature</key> <string>HB##</string> <key>CFBundleVersion</key> - <string>0.3</string> + <string>0.4</string> <key>NSMainNibFile</key> <string>MainMenu</string> <key>NSPrincipalClass</key> @@ -291,6 +294,8 @@ 4D929FEC0527903D00A80101, 4D6615EA05288C2300A80101, 4D857591052B78E300C39CA9, + 4D358C020534A91300D654EB, + 4D358C050534AB8100D654EB, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -311,6 +316,7 @@ 29B9732CFDCFA39411CA2CEA, 4DF3C8CE052889CD00A80101, 4D857590052B78E300C39CA9, + 4D358C030534A91300D654EB, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -391,6 +397,43 @@ settings = { }; }; + 4D358C000534A91300D654EB = { + fileEncoding = 30; + isa = PBXFileReference; + path = TargetSizeField.h; + refType = 4; + }; + 4D358C010534A91300D654EB = { + fileEncoding = 30; + isa = PBXFileReference; + path = TargetSizeField.mm; + refType = 4; + }; + 4D358C020534A91300D654EB = { + fileRef = 4D358C000534A91300D654EB; + isa = PBXBuildFile; + settings = { + }; + }; + 4D358C030534A91300D654EB = { + fileRef = 4D358C010534A91300D654EB; + isa = PBXBuildFile; + settings = { + }; + }; + 4D358C040534AB8100D654EB = { + fileEncoding = 30; + isa = PBXFileReference; + name = Common.h; + path = /Users/titer/HandBrake/core/Common.h; + refType = 0; + }; + 4D358C050534AB8100D654EB = { + fileRef = 4D358C040534AB8100D654EB; + isa = PBXBuildFile; + settings = { + }; + }; 4D6615EA05288C2300A80101 = { fileRef = 4DF3C8CB052889CD00A80101; isa = PBXBuildFile; @@ -557,13 +600,13 @@ 4DF3C8CB052889CD00A80101 = { fileEncoding = 30; isa = PBXFileReference; - path = HBController.h; + path = Controller.h; refType = 4; }; 4DF3C8CC052889CD00A80101 = { fileEncoding = 30; isa = PBXFileReference; - path = HBController.mm; + path = Controller.mm; refType = 4; }; 4DF3C8CE052889CD00A80101 = { diff --git a/macosx/PictureGLView.h b/macosx/PictureGLView.h index effbf3ee2..06e5a16e1 100644 --- a/macosx/PictureGLView.h +++ b/macosx/PictureGLView.h @@ -4,7 +4,7 @@ #include "Manager.h" -@interface PictureGLView : NSOpenGLView +@interface HBPictureGLView : NSOpenGLView { HBManager * fManager; diff --git a/macosx/PictureGLView.mm b/macosx/PictureGLView.mm index 72e564141..79103f6b6 100644 --- a/macosx/PictureGLView.mm +++ b/macosx/PictureGLView.mm @@ -2,7 +2,7 @@ #include "PictureGLView.h" -@implementation PictureGLView +@implementation HBPictureGLView - (void) SetManager: (HBManager*) manager { diff --git a/macosx/TargetSizeField.h b/macosx/TargetSizeField.h new file mode 100644 index 000000000..12224cae7 --- /dev/null +++ b/macosx/TargetSizeField.h @@ -0,0 +1,23 @@ +/* $Id: TargetSizeField.h,v 1.2 2003/10/09 23:33:36 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 "Common.h" + +@interface HBTargetSizeField : NSTextField + +{ + HBTitle * fTitle; + IBOutlet NSTextField * fBitrateField; + IBOutlet NSPopUpButton * fSecondaryLanguagePopUp; + IBOutlet NSPopUpButton * fAudioBitratePopUp; +} + +- (void) SetHBTitle: (HBTitle *) title; +- (void) UpdateBitrate; + +@end diff --git a/macosx/TargetSizeField.mm b/macosx/TargetSizeField.mm new file mode 100644 index 000000000..0c43701fb --- /dev/null +++ b/macosx/TargetSizeField.mm @@ -0,0 +1,64 @@ +/* $Id: TargetSizeField.mm,v 1.4 2003/10/09 23:33:36 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 "TargetSizeField.h" + +@implementation HBTargetSizeField + +- (void) textDidBeginEditing: (NSNotification *) notification +{ + [self UpdateBitrate]; + [super textDidBeginEditing: notification]; +} + +- (void) textDidEndEditing: (NSNotification *) notification +{ + [self UpdateBitrate]; + [super textDidEndEditing: notification]; +} + +- (void) textDidChange: (NSNotification *) notification +{ + [self UpdateBitrate]; + [super textDidChange: notification]; +} + +- (void) SetHBTitle: (HBTitle*) title +{ + fTitle = title; +} + +- (void) UpdateBitrate +{ + int64_t available; + available = (int64_t) [self intValue] * 1024 * 1024; + + /* AVI headers */ + available -= 2048; + + /* Video chunk headers (8 bytes / frame) + and index (16 bytes / frame) */ + available -= 24 * fTitle->fLength * fTitle->fRate / fTitle->fScale; + + /* Audio tracks */ + available -= ( ( [[fSecondaryLanguagePopUp titleOfSelectedItem] + compare: @"None"] == NSOrderedSame ) ? 1 : 2 ) * + ( fTitle->fLength * + [[fAudioBitratePopUp titleOfSelectedItem] intValue] * + 128 + 24 * fTitle->fLength * 44100 / 1152 ); + + if( available < 0 ) + { + [fBitrateField setIntValue: 0]; + } + else + { + [fBitrateField setIntValue: + available / ( 128 * fTitle->fLength )]; + } +} + +@end diff --git a/test/Test.cpp b/test/Test.cpp index d0d5ec9ea..4567f74b6 100644 --- a/test/Test.cpp +++ b/test/Test.cpp @@ -1,4 +1,4 @@ -/* $Id: Test.cpp,v 1.5 2003/10/05 14:28:40 titer Exp $ +/* $Id: Test.cpp,v 1.8 2003/10/13 10:58:24 titer Exp $ This file is part of the HandBrake source code. Homepage: <http://beos.titer.org/handbrake/>. @@ -27,6 +27,8 @@ int main( int argc, char ** argv ) char * device = NULL; char * outputFile = NULL; int titleIdx = 1; + int audio1Idx = 1; + int audio2Idx = 0; bool twoPass = false; bool deinterlace = false; int width = 0; @@ -34,10 +36,13 @@ int main( int argc, char ** argv ) int bottomCrop = 0; int leftCrop = 0; int rightCrop = 0; + int cpuCount = 0; + int vBitrate = 1024; + int aBitrate = 128; /* Parse command line */ int c; - while( ( c = getopt( argc, argv, "vd:o:t:piw:j:k:l:m:" ) ) != -1 ) + while( ( c = getopt( argc, argv, "vd:o:t:a:b:piw:j:k:l:m:c:e:f:" ) ) != -1 ) { switch( c ) { @@ -57,6 +62,14 @@ int main( int argc, char ** argv ) titleIdx = atoi( optarg ); break; + case 'a': + audio1Idx = atoi( optarg ); + break; + + case 'b': + audio2Idx = atoi( optarg ); + break; + case 'p': twoPass = true; break; @@ -85,6 +98,18 @@ int main( int argc, char ** argv ) rightCrop = atoi( optarg ); break; + case 'c': + cpuCount = atoi( optarg ); + break; + + case 'e': + vBitrate = atoi( optarg ); + break; + + case 'f': + aBitrate = atoi( optarg ); + break; + default: break; } @@ -96,20 +121,25 @@ int main( int argc, char ** argv ) 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" ); + " -v verbose output\n" + " -t <value> select a title (default is 1)\n" + " -a <value> primary audio channel (default is 1)\n" + " -b <value> secondary audio channel (default is none)\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" + " -c <value> CPU count\n" + " -e <value> Video bitrate (default is 1024)\n" + " -f <value> Audio bitrate (default is 128)\n" ); return 1; } /* Create the manager thread */ - HBManager * manager = new HBManager( debug ); + HBManager * manager = new HBManager( debug, cpuCount ); /* Tell the manager to scan the specified volume */ manager->ScanVolumes( device ); @@ -183,10 +213,16 @@ int main( int argc, char ** argv ) title->fBottomCrop = bottomCrop; title->fLeftCrop = leftCrop; title->fRightCrop = rightCrop; + title->fBitrate = vBitrate; - HBAudio * audio = (HBAudio*) title->fAudioList->ItemAt( 0 ); + HBAudio * audio1 = + (HBAudio*) title->fAudioList->ItemAt( audio1Idx - 1 ); + HBAudio * audio2 = + (HBAudio*) title->fAudioList->ItemAt( audio2Idx - 1 ); + if( audio1 ) audio1->fOutBitrate = aBitrate; + if( audio2 ) audio2->fOutBitrate = aBitrate; - manager->StartRip( title, audio, NULL, outputFile ); + manager->StartRip( title, audio1, audio2, outputFile ); break; } |