diff options
author | handbrake <[email protected]> | 2006-01-14 13:05:49 +0000 |
---|---|---|
committer | handbrake <[email protected]> | 2006-01-14 13:05:49 +0000 |
commit | 5824c4979fbc54ae3d3015c07cbf6fa4aea7516d (patch) | |
tree | 49ba3bbe1f8d8166fa4f7f964055d4011d2deca0 | |
parent | f013e3544c0bdf17348d617a467af0e4fde0f545 (diff) |
HandBrake 0.5
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@7 b64f7644-9d1e-0410-96f1-a4d463321fa5
86 files changed, 6210 insertions, 5392 deletions
@@ -1,117 +1,123 @@ HandBrake uses a lot of cool libraries from the GNU/Linux world. Thank their authors ! -libdvdcss authors : +liba52 authors: + Aaron Holtzman + Michel Lespinasse + Gildas Bazin + Billy Biggs + Eduard Hasenleithner + H�kan Hjort + Charles M. Hannum + Chris Hodges + Michael Holzt + Angelos Keromytis + David I. Lehn + Don Mahurin + Jim Miller + Takefumi Sayo + Shoji Tokunaga -Billy Biggs -St�phane Borel -H�kan Hjort -Samuel Hocevar -Eugenio Jarosiewicz -Jon Lech Johansen -Markus Kuespert -Pascal Levesque -Steven M. Schultz -David Sieb�rger -Alex Strelnikov -German Tischler -Gildas Bazin +libavcodec authors: + Fabrice Bellard + Alex Beregszaszi + Brian Foley + Arpad Gereoffy + Philip Gladstone + Falk Hueffner + Zdenek Kabelac + Nick Kurshev + Michael Niedermayer + Fran�ois Revol + Dieter Shirley + Juan J. Sierralta + Lionel Ulmer -libdvdread authors : +libdvdcss authors: + Billy Biggs + St�phane Borel + H�kan Hjort + Samuel Hocevar + Eugenio Jarosiewicz + Jon Lech Johansen + Markus Kuespert + Pascal Levesque + Steven M. Schultz + David Sieb�rger + Alex Strelnikov + German Tischler + Gildas Bazin -Bj�rn Englund -H�kan Hjort -Billy Biggs -Christian Wolff +libdvdread authors: + Bj�rn Englund + H�kan Hjort + Billy Biggs + Christian Wolff -libdvdplay authors : +libdvdplay authors: + H�kan Hjort + Martin Norb�ck + St�phane Borel -H�kan Hjort -Martin Norb�ck -St�phane Borel +libmp3lame authors: + Mike Cheng + Robert Hegemann + Frank Klemm + Alexander Leidinger + Naoki Shibata + Mark Taylor + Takehiro Tominiga + Iv�n Cavero Belaunde + Gabriel Bouvigne + Florian Bomers + CISC + John Dahlstrom + John Dee + Albert Faber + Peter Gubanov + Lars Magne Ingebrigtsen + Yosi Markovich + Zdenek Kabelac + Iwasa Kazmi + Guillaume Lessard + Steve Lhomme + Don Melton + Viral Shah + Acy Stapp + Roel VdB -mpeg2dec authors : +libmpeg2 authors: + Aaron Holtzman + Michel Lespinasse + Bruno Barreyra + Gildas Bazin + Alexander W. Chin + Stephen Crowley + Didier Gautheron + Ryan C. Gordon + Peter Gubanov + H�kan Hjort + Nicolas Joly + Gerd Knorr + David I. Lehn + Olie Lho + Rick Niles + Real Ouellet + Bajusz Peter + Franck Sicard + Brion Vibber + Martin Vogt + Fredrik Vraalsen -Aaron Holtzman -Michel Lespinasse -Bruno Barreyra -Gildas Bazin -Alexander W. Chin -Stephen Crowley -Didier Gautheron -Ryan C. Gordon -Peter Gubanov -H�kan Hjort -Nicolas Joly -Gerd Knorr -David I. Lehn -Olie Lho -Rick Niles -Real Ouellet -Bajusz Peter -Franck Sicard -Brion Vibber -Martin Vogt -Fredrik Vraalsen - -Ffmpeg authors : - -Fabrice Bellard -Alex Beregszaszi -Brian Foley -Arpad Gereoffy -Philip Gladstone -Falk Hueffner -Zdenek Kabelac -Nick Kurshev -Michael Niedermayer -Fran�ois Revol -Dieter Shirley -Juan J. Sierralta -Lionel Ulmer - -a52dec authors : - -Aaron Holtzman -Michel Lespinasse -Gildas Bazin -Billy Biggs -Eduard Hasenleithner -H�kan Hjort -Charles M. Hannum -Chris Hodges -Michael Holzt -Angelos Keromytis -David I. Lehn -Don Mahurin -Jim Miller -Takefumi Sayo -Shoji Tokunaga - -lame authors : - -Mike Cheng -Robert Hegemann -Frank Klemm -Alexander Leidinger -Naoki Shibata -Mark Taylor -Takehiro Tominiga -Iv�n Cavero Belaunde -Gabriel Bouvigne -Florian Bomers -CISC -John Dahlstrom -John Dee -Albert Faber -Peter Gubanov -Lars Magne Ingebrigtsen -Yosi Markovich -Zdenek Kabelac -Iwasa Kazmi -Guillaume Lessard -Steve Lhomme -Don Melton -Viral Shah -Acy Stapp -Roel VdB +libxvidcore authors: + Christoph Lampert + Michael Militzer + Peter Ross + Benjamin Herrenschmidt + Daniel Smith + Dirk Knop + Edouard Gomez + Guillaume Morin + MinChen + Pascal Massimino + Radoslaw Czyz @@ -1,16 +1,20 @@ -# $Id: Jamfile,v 1.41 2003/10/16 13:46:32 titer Exp $ +# $Id: Jamfile,v 1.5 2003/11/07 22:28:30 titer Exp $ # # This file is part of the HandBrake source code. -# Homepage: <http://beos.titer.org/handbrake/>. +# Homepage: <http://handbrake.m0k.org/>. # It may be used under the terms of the GNU General Public License. -HB_VERSION = 0.4.1 ; +HB_VERSION = 0.5 ; # Compilers +CC = gcc ; C++ = g++ ; -LINK = g++ ; +LINK = gcc ; # Flags +CCFLAGS = $(CFLAGS) ; +CCFLAGS += -g -Wall -Werror ; +CCFLAGS += -DVERSION=\\\"$(HB_VERSION)\\\" -DSYS_$(OS) ; C++FLAGS = $(CPPFLAGS) ; C++FLAGS += -g -Wall -Werror ; C++FLAGS += -DVERSION=\\\"$(HB_VERSION)\\\" -DSYS_$(OS) ; @@ -18,15 +22,18 @@ LINKFLAGS = $(LDFLAGS) ; HDRS = core ; # Optims +CCFLAGS += -funroll-loops ; C++FLAGS += -funroll-loops ; OPTIM = -O3 ; # Libs -LINKLIBS = -ldvdplay -ldvdread -ldvdcss -lmpeg2 -lavcodec -la52 -lmp3lame ; +LINKLIBS = -ldvdplay -ldvdread -ldvdcss -lmpeg2 -lavcodec -la52 + -lmp3lame -lxvidcore ; # OS specific if $(OS) = BEOS { + CCFLAGS += -Wno-multichar ; C++FLAGS += -Wno-multichar ; LINKLIBS += -lbe -ltracker ; } @@ -36,9 +43,19 @@ else if $(OS) = LINUX } else if $(OS) = MACOSX { + CCFLAGS += -no-cpp-precomp ; + C++FLAGS += -no-cpp-precomp ; + LINKFLAGS += -multiply_defined suppress ; + # needed to clean HandBrake.app RM = rm -rf ; } +else if $(OS) = CYGWIN +{ + CCFLAGS += -mno-cygwin ; + C++FLAGS += -mno-cygwin ; + LINKFLAGS += -mno-cygwin ; +} # Do not remove temporary object files # There MUST be a cleaner way to do this @@ -46,36 +63,36 @@ actions quietly updated piecemeal together RmTemps { } -# Build HandBrake.app using ProjectBuilder +# Build HandBrake.app using Xcode rule OSXApp { - Clean clean : $(1) ; + Clean clean : $(1) macosx/build ; BuildOSXApp $(1) ; } actions BuildOSXApp { $(RM) HandBrake.app ; - ( cd macosx && pbxbuild ) && mv macosx/build/HandBrake.app . ; - $(RM) macosx/build ; + ( cd macosx && xcodebuild ) && cp -r macosx/build/HandBrake.app . ; } -Library core/libhb : core/Ac3Decoder.cpp core/AviMuxer.cpp - core/Common.cpp core/DVDReader.cpp core/Fifo.cpp - core/Manager.cpp core/Mp3Encoder.cpp - core/Mpeg2Decoder.cpp core/Mpeg4Encoder.cpp - core/MpegDemux.cpp core/Resizer.cpp - core/Scanner.cpp core/Thread.cpp core/Worker.cpp ; +Library core/libhb : core/Ac3Dec.c core/AviMux.c + core/Utils.c core/DVDRead.c core/Fifo.c + core/HandBrake.c core/Mp3Enc.c + core/Mpeg2Dec.c core/FfmpegEnc.c + core/MadDec.c core/Scale.c + core/Scan.c core/Thread.c core/Work.c + core/XvidEnc.c ; LinkLibraries HBTest : core/libhb.a ; -Main HBTest : test/Test.cpp ; +Main HBTest : test/test.c ; if $(OS) = BEOS { LinkLibraries HandBrake : core/libhb.a ; - Main HandBrake : beos/HandBrake.cpp beos/MainWindow.cpp + Main HandBrake : beos/HBApp.cpp beos/MainWindow.cpp beos/PictureWin.cpp beos/ScanView.cpp - beos/RipView.cpp ; + beos/RipView.cpp ; } if $(OS) = MACOSX @@ -1,4 +1,8 @@ -$Id: NEWS,v 1.11 2003/10/13 15:35:38 titer Exp $ +$Id: NEWS,v 1.3 2003/11/07 21:52:56 titer Exp $ + +Changes between 0.4 and 0.5 + - Bugfixes, rewrite of large parts of the core + - XviD encoding (1-pass only) Changes between 0.3 and 0.4 - Better multithreading @@ -1,8 +1,17 @@ -- General - + Use the DVD name in popup and for the name of the created file - + Show the current pass +- Core + Should be able to boost the audio volume + + Allow the intf to preview the latest encoded picture + + Finish and test the MPEG audio decoder + + More encoding options: B-frames, type of estimation, + type of scaling, etc + + Subtitle support + + Finish xvid encoding support (2-pass, more tests) + + Allow the user to split the file in x parts + + AAC & vorbis encoding support + + mp4 & mkv muxing support + +- All interfaces + + Use the DVD name in popup and for the name of the created file -- OSX port - + Preview in a drawer - + Prompt before overwriting a file +- BeOS interface + + Redo the picture panel diff --git a/beos/HandBrake.cpp b/beos/HBApp.cpp index b5f13196b..52afce815 100644 --- a/beos/HandBrake.cpp +++ b/beos/HBApp.cpp @@ -1,12 +1,12 @@ -/* $Id: HandBrake.cpp,v 1.8 2003/10/13 22:23:02 titer Exp $ +/* $Id: HBApp.cpp,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <signal.h> -#include "HandBrake.h" +#include "HBApp.h" #include "MainWindow.h" void SigHandler( int signal ) diff --git a/beos/HandBrake.h b/beos/HBApp.h index 7035b5487..fb5c41c38 100644 --- a/beos/HandBrake.h +++ b/beos/HBApp.h @@ -1,11 +1,11 @@ -/* $Id: HandBrake.h,v 1.7 2003/10/13 22:23:02 titer Exp $ +/* $Id: HBApp.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ -#ifndef HB_HANDBRAKE_H -#define HB_HANDBRAKE_H +#ifndef HB_HB_APP_H +#define HB_HB_APP_H #include <Application.h> diff --git a/beos/MainWindow.cpp b/beos/MainWindow.cpp index 613cf21df..bf52caa84 100644 --- a/beos/MainWindow.cpp +++ b/beos/MainWindow.cpp @@ -1,14 +1,13 @@ -/* $Id: MainWindow.cpp,v 1.19 2003/10/13 22:23:02 titer Exp $ +/* $Id: MainWindow.cpp,v 1.3 2003/11/07 21:52:56 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <Alert.h> #include <Application.h> #include <Screen.h> -#include "Manager.h" #include "MainWindow.h" #include "ScanView.h" #include "RipView.h" @@ -17,17 +16,16 @@ MainWindow::MainWindow() : BWindow( BRect( 0,0,10,10 ), "HandBrake " VERSION, B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE ) { - /* Init libhb & launch the manager thread */ - fManager = new HBManager( true ); + fHandle = HBInit( 1, 0 ); /* Add the scan view */ - fScanView = new ScanView( fManager ); - fRipView = new RipView( fManager ); + fScanView = new ScanView( fHandle ); + fRipView = new RipView( fHandle ); 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 ); @@ -45,7 +43,7 @@ bool MainWindow::QuitRequested() fDie = true; long exit_value; wait_for_thread( fUpdateThread, &exit_value ); - delete fManager; + HBClose( &fHandle ); /* Stop the application */ be_app->PostMessage( B_QUIT_REQUESTED ); @@ -62,7 +60,7 @@ void MainWindow::MessageReceived( BMessage * message ) alert = new BAlert( "About HandBrake", "HandBrake " VERSION "\n\n" "by Eric Petit <[email protected]>\n" - "Homepage : <http://beos.titer.org/handbrake/>\n\n" + "Homepage : <http://handbrake.m0k.org/>\n\n" "No, you don't want to know where this stupid app " "name comes from.\n\n" "Thanks to BGA for pointing out very cool bugs ;)", @@ -80,6 +78,7 @@ void MainWindow::MessageReceived( BMessage * message ) case B_SAVE_REQUESTED: case RIP_TITLE_POPUP: + case RIP_VIDEO_CODEC_POPUP: case RIP_BITRATE_RADIO: case RIP_TARGET_CONTROL: case RIP_CROP_BUTTON: @@ -88,7 +87,7 @@ void MainWindow::MessageReceived( BMessage * message ) case RIP_RIP_BUTTON: fRipView->MessageReceived( message ); break; - + default: BWindow::MessageReceived( message ); break; @@ -98,56 +97,64 @@ void MainWindow::MessageReceived( BMessage * message ) void MainWindow::UpdateInterface( MainWindow * _this ) { uint64_t time; + int64_t wait; while( !_this->fDie ) { /* Update every 0.1 sec */ time = system_time(); + _this->_UpdateInterface(); - snooze( 100000 - ( system_time() - time ) ); + + wait = 100000 - ( system_time() - time ); + if( wait > 0 ) + { + snooze( wait ); + } } } void MainWindow::_UpdateInterface() { - if( !fManager->NeedUpdate() ) - { - return; - } - - HBStatus status = fManager->GetStatus(); - if( !Lock() ) { fprintf( stderr, "Lock() failed\n" ); return; } + + int modeChanged; + HBStatus status; + + modeChanged = HBGetStatus( fHandle, &status ); - switch( status.fMode ) + switch( status.mode ) { case HB_MODE_UNDEF: - case HB_MODE_NEED_VOLUME: + case HB_MODE_NEED_DEVICE: break; - + case HB_MODE_SCANNING: - case HB_MODE_INVALID_VOLUME: - fScanView->UpdateIntf( status ); + case HB_MODE_INVALID_DEVICE: + fScanView->UpdateIntf( status, modeChanged ); break; case HB_MODE_READY_TO_RIP: + if( !modeChanged ) + break; + RemoveChild( fScanView ); ResizeTo( fRipView->Bounds().Width(), fRipView->Bounds().Height() ); AddChild( fRipView ); - fRipView->UpdateIntf( status ); + fRipView->UpdateIntf( status, modeChanged ); break; case HB_MODE_ENCODING: - case HB_MODE_SUSPENDED: + case HB_MODE_PAUSED: case HB_MODE_DONE: case HB_MODE_CANCELED: case HB_MODE_ERROR: - fRipView->UpdateIntf( status ); + fRipView->UpdateIntf( status, modeChanged ); break; default: diff --git a/beos/MainWindow.h b/beos/MainWindow.h index c4c32a711..5e50775bc 100644 --- a/beos/MainWindow.h +++ b/beos/MainWindow.h @@ -1,7 +1,7 @@ -/* $Id: MainWindow.h,v 1.10 2003/10/10 01:08:42 titer Exp $ +/* $Id: MainWindow.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ @@ -12,7 +12,7 @@ class ScanView; class RipView; -#include "Common.h" +#include "HandBrake.h" class MainWindow : public BWindow { @@ -25,7 +25,7 @@ class MainWindow : public BWindow static void UpdateInterface( MainWindow * _this ); void _UpdateInterface(); - HBManager * fManager; + HBHandle * fHandle; int fUpdateThread; volatile bool fDie; diff --git a/beos/PictureWin.cpp b/beos/PictureWin.cpp index 23aabe7c6..5667dbc3e 100644 --- a/beos/PictureWin.cpp +++ b/beos/PictureWin.cpp @@ -1,7 +1,7 @@ -/* $Id: PictureWin.cpp,v 1.5 2003/09/30 14:38:15 titer Exp $ +/* $Id: PictureWin.cpp,v 1.2 2003/11/06 14:36:54 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <Bitmap.h> @@ -12,24 +12,23 @@ #include <Slider.h> #include "PictureWin.h" -#include "Manager.h" #define UPDATE_BITMAP 'upbi' /* Handy way to access HBTitle members */ -#define fInWidth fTitle->fInWidth -#define fInHeight fTitle->fInHeight -#define fPixelWidth fTitle->fPixelWidth -#define fPixelHeight fTitle->fPixelHeight -#define fDeinterlace fTitle->fDeinterlace -#define fOutWidth fTitle->fOutWidth -#define fOutHeight fTitle->fOutHeight -#define fOutWidthMax fTitle->fOutWidthMax -#define fOutHeightMax fTitle->fOutHeightMax -#define fTopCrop fTitle->fTopCrop -#define fBottomCrop fTitle->fBottomCrop -#define fLeftCrop fTitle->fLeftCrop -#define fRightCrop fTitle->fRightCrop +#define fInWidth fTitle->inWidth +#define fInHeight fTitle->inHeight +#define fPixelWidth fTitle->pixelWidth +#define fPixelHeight fTitle->pixelHeight +#define fDeinterlace fTitle->deinterlace +#define fOutWidth fTitle->outWidth +#define fOutHeight fTitle->outHeight +#define fOutWidthMax fTitle->outWidthMax +#define fOutHeightMax fTitle->outHeightMax +#define fTopCrop fTitle->topCrop +#define fBottomCrop fTitle->bottomCrop +#define fLeftCrop fTitle->leftCrop +#define fRightCrop fTitle->rightCrop HBPictureView::HBPictureView( BRect rect, BBitmap * bitmap ) : BView( rect, NULL, B_FOLLOW_ALL, B_WILL_DRAW ) @@ -46,7 +45,7 @@ void HBPictureView::Draw( BRect rect ) } else { - Log( "HBPictureView::Draw() : LockLooper() failed" ); + fprintf( stderr, "LockLooper() failed\n" ); } BView::Draw( rect ); @@ -54,12 +53,12 @@ void HBPictureView::Draw( BRect rect ) /* Constructor */ -HBPictureWin::HBPictureWin( HBManager * manager, HBTitle * title ) +HBPictureWin::HBPictureWin( HBHandle * handle, HBTitle * title ) : BWindow( BRect( 0, 0, 0, 0 ), "Picture settings", B_FLOATING_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_ZOOMABLE | B_NOT_CLOSABLE ) { - fManager = manager; + fHandle = handle; fTitle = title; /* Resize & center */ @@ -101,7 +100,7 @@ HBPictureWin::HBPictureWin( HBManager * manager, HBTitle * title ) view->AddChild( pictureBox ); - /* Second box : resize & crop settings */ + /* Second box : scale & crop settings */ r = BRect( 10, fOutHeightMax + 75, fOutWidthMax + 31, fOutHeightMax + 235 ); BBox * settingsBox; @@ -189,8 +188,8 @@ void HBPictureWin::UpdateBitmap( int image ) fRightCrop = 2 * fRightCropSlider->Value(); fDeinterlace = ( fDeinterlaceCheck->Value() != 0 ); - uint8_t * preview = fManager->GetPreview( fTitle, image ); - for( uint32_t i = 0; i < fOutHeightMax + 2; i++ ) + uint8_t * preview = HBGetPreview( fHandle, fTitle, image ); + for( int i = 0; i < fOutHeightMax + 2; i++ ) { memcpy( ((uint8_t*) fBitmap->Bits()) + i * fBitmap->BytesPerRow(), @@ -201,7 +200,7 @@ void HBPictureWin::UpdateBitmap( int image ) if( !Lock() ) { - Log( "HBPictureWin::UpdateBitmap() : cannot Lock()" ); + fprintf( stderr, "Lock() failed\n" ); return; } diff --git a/beos/PictureWin.h b/beos/PictureWin.h index 909e8ea51..265eb8ad0 100644 --- a/beos/PictureWin.h +++ b/beos/PictureWin.h @@ -1,7 +1,7 @@ -/* $Id: PictureWin.h,v 1.3 2003/09/30 14:38:15 titer Exp $ +/* $Id: PictureWin.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #ifndef HB_PICTURE_WIN_H @@ -12,8 +12,7 @@ class BSlider; class BCheckBox; -/* libhb headers */ -#include "Common.h" +#include "HandBrake.h" class HBPictureView : public BView { @@ -28,14 +27,14 @@ class HBPictureView : public BView class HBPictureWin : public BWindow { public: - HBPictureWin( HBManager * manager, HBTitle * title ); + HBPictureWin( HBHandle * handle, HBTitle * title ); virtual void MessageReceived( BMessage * message ); void UpdateBitmap( int which ); private: - HBManager * fManager; + HBHandle * fHandle; HBTitle * fTitle; /* GUI */ diff --git a/beos/RipView.cpp b/beos/RipView.cpp index 180ba23ff..756090510 100644 --- a/beos/RipView.cpp +++ b/beos/RipView.cpp @@ -1,7 +1,7 @@ -/* $Id: RipView.cpp,v 1.6 2003/10/13 23:42:03 titer Exp $ +/* $Id: RipView.cpp,v 1.3 2003/11/07 21:52:56 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <Box.h> @@ -19,14 +19,13 @@ #include "RipView.h" #include "PictureWin.h" -#include "Manager.h" #define DEFAULT_FILE "/boot/home/Desktop/Movie.avi" -RipView::RipView( HBManager * manager ) +RipView::RipView( HBHandle * handle ) : BView( BRect( 0,0,400,480 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW ) { - fManager = manager; + fHandle = handle; BRect r; SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); @@ -85,7 +84,7 @@ RipView::RipView( HBManager * manager ) /* Crop */ r = BRect( fVideoBox->Bounds().Width() - 120, 120, fVideoBox->Bounds().Width() - 10, 140 ); - fCropButton = new BButton( r, NULL, "Crop & Resize...", + fCropButton = new BButton( r, NULL, "Crop & Scale...", new BMessage( RIP_CROP_BUTTON ) ); fVideoBox->AddChild( fCropButton ); @@ -172,7 +171,10 @@ RipView::RipView( HBManager * manager ) AddChild( fStartButton ); /* Fill popups */ - fVideoCodecPopUp->AddItem( new BMenuItem( "MPEG-4", NULL ) ); + fVideoCodecPopUp->AddItem( new BMenuItem( "MPEG-4 (Ffmpeg)", + new BMessage( RIP_VIDEO_CODEC_POPUP ) ) ); + fVideoCodecPopUp->AddItem( new BMenuItem( "MPEG-4 (XviD)", + new BMessage( RIP_VIDEO_CODEC_POPUP ) ) ); fVideoCodecPopUp->ItemAt( 0 )->SetMarked( true ); fAudioCodecPopUp->AddItem( new BMenuItem( "MP3", NULL ) ); fAudioCodecPopUp->ItemAt( 0 )->SetMarked( true ); @@ -208,7 +210,7 @@ void RipView::MessageReceived( BMessage * message ) case RIP_TITLE_POPUP: { int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); - HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, index ); /* Empty current popups */ BMenuItem * item; @@ -225,13 +227,13 @@ void RipView::MessageReceived( BMessage * message ) /* Show new languages */ HBAudio * audio; - for( uint32_t i = 0; i < title->fAudioList->CountItems(); i++ ) + for( int i = 0; i < HBListCountItems( title->audioList ); i++ ) { - audio = (HBAudio*) title->fAudioList->ItemAt( i ); + audio = (HBAudio*) HBListItemAt( title->audioList, i ); fLanguagePopUp->AddItem( - new BMenuItem( audio->fDescription, NULL ) ); + new BMenuItem( audio->language, NULL ) ); fSecondaryLanguagePopUp->AddItem( - new BMenuItem( audio->fDescription, + new BMenuItem( audio->language, new BMessage( RIP_TARGET_CONTROL ) ) ); } fLanguagePopUp->ItemAt( 0 )->SetMarked( true ); @@ -241,11 +243,25 @@ void RipView::MessageReceived( BMessage * message ) fSecondaryLanguagePopUp->CountItems() - 1 )->SetMarked( true ); fSecondaryLanguageField->SetEnabled( - ( title->fAudioList->CountItems() > 1 ) ); + ( HBListCountItems( title->audioList ) > 1 ) ); break; } + case RIP_VIDEO_CODEC_POPUP: + { + if( fVideoCodecPopUp->IndexOf( fVideoCodecPopUp->FindMarked() ) ) + { + fTwoPassCheck->SetValue( 0 ); + fTwoPassCheck->SetEnabled( false ); + } + else + { + fTwoPassCheck->SetEnabled( true ); + } + break; + } + case RIP_BITRATE_RADIO: { if( fCustomBitrateRadio->Value() ) @@ -271,7 +287,7 @@ void RipView::MessageReceived( BMessage * message ) int64_t available; int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); - HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, index ); available = (int64_t) 1024 * 1024 * atoi( fTargetSizeControl->Text() ); @@ -281,16 +297,16 @@ void RipView::MessageReceived( BMessage * message ) /* Video chunk headers (8 bytes / frame) and and index (16 bytes / frame) */ - available -= 24 * title->fLength * title->fRate / - title->fScale; + available -= 24 * title->length * title->rate / + title->rateBase; /* Audio tracks */ available -= ( strcmp( fSecondaryLanguagePopUp->FindMarked()->Label(), "None" ) ? 2 : 1 ) * - ( title->fLength * + ( title->length * atoi( fAudioBitratePopUp->FindMarked()->Label() ) * 128 + - 24 * title->fLength * 44100 / 1152 ); + 24 * title->length * 44100 / 1152 ); char string[1024]; memset( string, 0, 1024 ); if( available < 0 ) @@ -300,7 +316,7 @@ void RipView::MessageReceived( BMessage * message ) else { sprintf( string, "%lld", available / - ( 128 * title->fLength ) ); + ( 128 * title->length ) ); } fCustomBitrateControl->SetText( string ); break; @@ -309,10 +325,10 @@ void RipView::MessageReceived( BMessage * message ) case RIP_CROP_BUTTON: { int index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); - HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, index ); HBPictureWin * win; - win = new HBPictureWin( fManager, title ); + win = new HBPictureWin( fHandle, title ); win->Show(); break; } @@ -341,11 +357,11 @@ void RipView::MessageReceived( BMessage * message ) { if( strcmp( fSuspendButton->Label(), "Suspend" ) ) { - fManager->ResumeRip(); + HBResumeRip( fHandle ); } else { - fManager->SuspendRip(); + HBPauseRip( fHandle ); } break; @@ -355,7 +371,7 @@ void RipView::MessageReceived( BMessage * message ) { if( strcmp( fStartButton->Label(), "Rip !" ) ) { - fManager->StopRip(); + HBStopRip( fHandle ); } else { @@ -363,29 +379,32 @@ void RipView::MessageReceived( BMessage * message ) /* Get asked title & languages */ index = fTitlePopUp->IndexOf( fTitlePopUp->FindMarked() ); - HBTitle * title = (HBTitle*) fTitleList->ItemAt( index ); + HBTitle * title = (HBTitle*) HBListItemAt( fTitleList, index ); index = fLanguagePopUp->IndexOf( fLanguagePopUp->FindMarked() ); HBAudio * audio1 = - (HBAudio*) title->fAudioList->ItemAt( index ); + (HBAudio*) HBListItemAt( title->audioList, index ); index = fSecondaryLanguagePopUp->IndexOf( fSecondaryLanguagePopUp->FindMarked() ); HBAudio * audio2 = - (HBAudio*) title->fAudioList->ItemAt( index ); + (HBAudio*) HBListItemAt( title->audioList, index ); /* Use user settings */ - title->fBitrate = atoi( fCustomBitrateControl->Text() ); - title->fTwoPass = ( fTwoPassCheck->Value() != 0 ); - audio1->fOutBitrate = + title->file = strdup( fFileControl->Text() ); + title->bitrate = atoi( fCustomBitrateControl->Text() ); + title->twoPass = ( fTwoPassCheck->Value() != 0 ); + title->codec = fVideoCodecPopUp->IndexOf( + fVideoCodecPopUp->FindMarked() ) ? HB_CODEC_XVID : + HB_CODEC_FFMPEG; + audio1->outBitrate = atoi( fAudioBitratePopUp->FindMarked()->Label() ); if( audio2 ) { - audio2->fOutBitrate = + audio2->outBitrate = atoi( fAudioBitratePopUp->FindMarked()->Label() ); } /* Let libhb do the job */ - fManager->StartRip( title, audio1, audio2, - (char*) fFileControl->Text() ); + HBStartRip( fHandle, title, audio1, audio2 ); } break; } @@ -396,23 +415,26 @@ void RipView::MessageReceived( BMessage * message ) } } -void RipView::UpdateIntf( HBStatus status ) +void RipView::UpdateIntf( HBStatus status, int modeChanged ) { - switch( status.fMode ) + switch( status.mode ) { case HB_MODE_READY_TO_RIP: { - fTitleList = status.fTitleList; + if( !modeChanged ) + break; + + fTitleList = status.titleList; HBTitle * title; - for( uint32_t i = 0; i < fTitleList->CountItems(); i++ ) + for( int i = 0; i < HBListCountItems( fTitleList ); i++ ) { - title = (HBTitle*) fTitleList->ItemAt( i ); + title = (HBTitle*) HBListItemAt( fTitleList, 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 ); + sprintf( string, "%d (%02d:%02d:%02d)", + title->index, title->length / 3600, + ( title->length % 3600 ) / 60, + title->length % 60 ); fTitlePopUp->AddItem( new BMenuItem( string, new BMessage( RIP_TITLE_POPUP ) ) ); } @@ -423,23 +445,30 @@ void RipView::UpdateIntf( HBStatus status ) 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 ) + if( modeChanged ) + { + 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 ); + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( true ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->SetEnabled( true ); + } + + if( !status.position ) { fStatusBar->Update( - fStatusBar->CurrentValue(), "Starting..." ); @@ -449,163 +478,175 @@ void RipView::UpdateIntf( HBStatus status ) 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 - + 100 * status.position, + status.frameRate, + status.remainingTime / 3600, + ( status.remainingTime % 3600 ) / 60, + status.remainingTime % 60 ); + fStatusBar->Update( 100 * status.position - fStatusBar->CurrentValue(), string ); } - - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetEnabled( true ); - fStartButton->SetLabel( "Cancel" ); - fStartButton->SetEnabled( true ); break; } - case HB_MODE_SUSPENDED: + case HB_MODE_PAUSED: { - 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" ); + if( modeChanged ) + { + 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 ); + fSuspendButton->SetLabel( "Resume" ); + fSuspendButton->SetEnabled( true ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->SetEnabled( true ); + } - fSuspendButton->SetLabel( "Resume" ); - fSuspendButton->SetEnabled( true ); - fStartButton->SetLabel( "Cancel" ); - fStartButton->SetEnabled( true ); + fStatusBar->Update( 100 * status.position - + fStatusBar->CurrentValue(), "Suspended" ); 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 ); + if( modeChanged ) + { + 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 ); + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Cancel" ); + fStartButton->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 ); + if( modeChanged ) + { + 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 ); + + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Rip !" ); + fStartButton->SetEnabled( true ); + MessageReceived( new BMessage( RIP_VIDEO_CODEC_POPUP ) ); + } 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 ); + if( modeChanged ) + { + 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 ); + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Rip !" ); + fStartButton->SetEnabled( true ); + MessageReceived( new BMessage( RIP_VIDEO_CODEC_POPUP ) ); + } 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 ); + if( modeChanged ) + { + 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 ); + fSuspendButton->SetLabel( "Suspend" ); + fSuspendButton->SetEnabled( false ); + fStartButton->SetLabel( "Rip !" ); + fStartButton->SetEnabled( true ); + MessageReceived( new BMessage( RIP_VIDEO_CODEC_POPUP ) ); + } fStatusBar->Update( - fStatusBar->CurrentValue(), "Error." ); - - fSuspendButton->SetLabel( "Suspend" ); - fSuspendButton->SetEnabled( false ); - fStartButton->SetLabel( "Rip !" ); - fStartButton->SetEnabled( true ); break; } diff --git a/beos/RipView.h b/beos/RipView.h index d487b2b99..27d9831a0 100644 --- a/beos/RipView.h +++ b/beos/RipView.h @@ -1,7 +1,7 @@ -/* $Id: RipView.h,v 1.5 2003/10/13 22:23:02 titer Exp $ +/* $Id: RipView.h,v 1.3 2003/11/07 21:52:56 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ @@ -19,25 +19,26 @@ class BRadioButton; class BStatusBar; class BTextControl; -#include "Common.h" +#include "HandBrake.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' +#define RIP_TITLE_POPUP 'rtip' +#define RIP_VIDEO_CODEC_POPUP 'rvcp' +#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 ); + RipView( HBHandle * handle ); void MessageReceived( BMessage * message ); - void UpdateIntf( HBStatus status ); + void UpdateIntf( HBStatus status, int modeChanged ); private: - HBManager * fManager; + HBHandle * fHandle; HBList * fTitleList; BBox * fVideoBox; diff --git a/beos/ScanView.cpp b/beos/ScanView.cpp index fb5d722e8..24c66db7f 100644 --- a/beos/ScanView.cpp +++ b/beos/ScanView.cpp @@ -1,7 +1,7 @@ -/* $Id: ScanView.cpp,v 1.4 2003/10/13 23:42:03 titer Exp $ +/* $Id: ScanView.cpp,v 1.2 2003/11/06 14:36:54 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <fs_info.h> @@ -21,13 +21,12 @@ #include <TextControl.h> #include <VolumeRoster.h> -#include "Manager.h" #include "ScanView.h" -ScanView::ScanView( HBManager * manager ) +ScanView::ScanView( HBHandle * handle ) : BView( BRect( 0,0,400,190 ), NULL, B_FOLLOW_ALL, B_WILL_DRAW ) { - fManager = manager; + fHandle = handle; BRect r; SetViewColor( ui_color( B_PANEL_BACKGROUND_COLOR ) ); @@ -125,12 +124,14 @@ void ScanView::MessageReceived( BMessage * message ) { if( fRadioDetected->Value() ) { - fManager->ScanVolumes( (char*) - fPopUp->FindMarked()->Label() ); + HBScanDevice( fHandle, + (char*) fPopUp->FindMarked()->Label(), + 0 ); } else { - fManager->ScanVolumes( (char*) fFolderControl->Text() ); + HBScanDevice( fHandle, + (char*) fFolderControl->Text(), 0 ); } break; } @@ -140,36 +141,41 @@ void ScanView::MessageReceived( BMessage * message ) } } -void ScanView::UpdateIntf( HBStatus status ) +void ScanView::UpdateIntf( HBStatus status, int modeChanged ) { - switch( status.fMode ) + switch( status.mode ) { case HB_MODE_SCANNING: { - fRadioDetected->SetEnabled( false ); - fRadioFolder->SetEnabled( false ); - fField->SetEnabled( false ); - fFolderControl->SetEnabled( false ); - fBrowseButton->SetEnabled( false ); - fOpenButton->SetEnabled( false ); + if( modeChanged ) + { + 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 ) + if( !status.scannedTitle ) { - sprintf( string, "Opening %s...", - status.fScannedVolume ); + sprintf( string, "Opening device..." ); } else { - sprintf( string, "Scanning %s, title %d...", - status.fScannedVolume, status.fScannedTitle ); + sprintf( string, "Scanning title %d...", + status.scannedTitle ); } fStatusString->SetText( string ); break; } - case HB_MODE_INVALID_VOLUME: + case HB_MODE_INVALID_DEVICE: { + if( !modeChanged ) + break; + fRadioDetected->SetEnabled( true ); fRadioFolder->SetEnabled( true ); diff --git a/beos/ScanView.h b/beos/ScanView.h index 5e2514b54..11ed342cc 100644 --- a/beos/ScanView.h +++ b/beos/ScanView.h @@ -1,7 +1,7 @@ -/* $Id: ScanView.h,v 1.2 2003/10/13 22:23:02 titer Exp $ +/* $Id: ScanView.h,v 1.2 2003/11/06 14:36:54 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #ifndef HB_SCAN_VIEW_H @@ -16,7 +16,7 @@ class BRadioButton; class BStringView; class BTextControl; -#include "Common.h" +#include "HandBrake.h" #define SCAN_RADIO 'scra' #define SCAN_BROWSE_BUTTON 'sbrb' @@ -25,14 +25,14 @@ class BTextControl; class ScanView : public BView { public: - ScanView( HBManager * manager ); + ScanView( HBHandle * handle ); void MessageReceived( BMessage * message ); - void UpdateIntf( HBStatus status ); + void UpdateIntf( HBStatus status, int modeChanged ); private: void DetectVolumes(); - HBManager * fManager; + HBHandle * fHandle; BRadioButton * fRadioDetected; BRadioButton * fRadioFolder; diff --git a/core/Ac3Dec.c b/core/Ac3Dec.c new file mode 100644 index 000000000..d5430d49e --- /dev/null +++ b/core/Ac3Dec.c @@ -0,0 +1,219 @@ +/* $Id: Ac3Dec.c,v 1.4 2003/11/04 20:16:44 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Ac3Dec.h" +#include "Fifo.h" +#include "Work.h" + +#include <a52dec/a52.h> + +/* Local prototypes */ +static int Ac3DecWork( HBWork * ); +static int GetBytes( HBAc3Dec *, int ); + +struct HBAc3Dec +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBAudio * audio; + + /* liba52 stuff */ + a52_state_t * state; + int inFlags; + int outFlags; + float sampleLevel; + + /* Buffers */ + uint8_t ac3Frame[3840]; /* Max size of a A52 frame */ + int ac3FrameSize; /* In bytes */ + HBBuffer * ac3Buffer; + int ac3BufferPos; /* In bytes */ + int nextFrameSize; /* In bytes */ + float position; + HBBuffer * rawBuffer; +}; + +HBAc3Dec * HBAc3DecInit( HBHandle * handle, HBAudio * audio ) +{ + HBAc3Dec * a; + if( !( a = malloc( sizeof( HBAc3Dec ) ) ) ) + { + HBLog( "HBAc3DecInit: malloc() failed, gonna crash" ); + return NULL; + } + + a->name = strdup( "Ac3Dec" ); + a->work = Ac3DecWork; + + a->handle = handle; + a->audio = audio; + + /* Init liba52 */ + a->state = a52_init( 0 ); + a->inFlags = 0; + + /* Let it do the downmixing */ + a->outFlags = A52_STEREO; + + /* Lame wants samples from -32768 to 32768 */ + a->sampleLevel = 32768.0; + + a->ac3FrameSize = 0; + a->ac3Buffer = NULL; + a->ac3BufferPos = 0; + a->nextFrameSize = 0; + a->position = 0.0; + a->rawBuffer = NULL; + + return a; +} + +void HBAc3DecClose( HBAc3Dec ** _a ) +{ + HBAc3Dec * a = *_a; + + if( a->ac3Buffer ) HBBufferClose( &a->ac3Buffer ); + if( a->rawBuffer ) HBBufferClose( &a->rawBuffer ); + a52_free( a->state ); + free( a->name ); + free( a ); + + *_a = NULL; +} + +static int Ac3DecWork( HBWork * w ) +{ + HBAc3Dec * a = (HBAc3Dec*) w; + HBAudio * audio = a->audio; + + int didSomething = 0; + + /* Push decoded buffer */ + if( a->rawBuffer ) + { + if( HBFifoPush( audio->rawFifo, &a->rawBuffer ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + } + + /* Get a frame header (7 bytes) */ + if( a->ac3FrameSize < 7 ) + { + if( GetBytes( a, 7 ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + a->nextFrameSize = a52_syncinfo( a->ac3Frame, &a->inFlags, + &audio->inSampleRate, + &audio->inBitrate ); + + if( !a->nextFrameSize ) + { + HBLog( "HBAc3Dec: a52_syncinfo() failed" ); + HBErrorOccured( a->handle, HB_ERROR_A52_SYNC ); + return didSomething; + } + } + + /* Get the whole frame */ + if( a->ac3FrameSize >= 7 ) + { + sample_t * samples; + HBBuffer * rawBuffer; + int i; + + if( GetBytes( a, a->nextFrameSize ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + /* Feed liba52 */ + a52_frame( a->state, a->ac3Frame, &a->outFlags, + &a->sampleLevel, 0 ); + a->ac3FrameSize = 0; + + /* 6 blocks per frame, 256 samples per block, 2 channels */ + rawBuffer = HBBufferInit( 12 * 256 * sizeof( float ) ); + rawBuffer->position = a->position; + + for( i = 0; i < 6; i++ ) + { + /* Decode a block */ + a52_block( a->state ); + + /* Get a pointer to the raw data */ + samples = a52_samples( a->state ); + + /* Copy left channel data */ + memcpy( rawBuffer->data + i * 256 * sizeof( float ), + samples, + 256 * sizeof( float ) ); + + /* Copy right channel data */ + memcpy( rawBuffer->data + ( 6 + i ) * 256 * sizeof( float ), + samples + 256, + 256 * sizeof( float ) ); + } + + a->rawBuffer = rawBuffer; + } + + return didSomething; +} + +static int GetBytes( HBAc3Dec * a, int size ) +{ + int i; + + while( a->ac3FrameSize < size ) + { + if( !a->ac3Buffer ) + { + if( !( a->ac3Buffer = HBFifoPop( a->audio->ac3Fifo ) ) ) + { + return 0; + } + a->ac3BufferPos = 0; + a->position = a->ac3Buffer->position; + + if( a->ac3Buffer->last ) + { + HBDone( a->handle ); + } + } + + i = MIN( size - a->ac3FrameSize, + a->ac3Buffer->size - a->ac3BufferPos ); + memcpy( a->ac3Frame + a->ac3FrameSize, + a->ac3Buffer->data + a->ac3BufferPos, + i ); + a->ac3FrameSize += i; + a->ac3BufferPos += i; + + if( a->ac3BufferPos == a->ac3Buffer->size ) + { + HBBufferClose( &a->ac3Buffer ); + } + } + + return 1; +} + diff --git a/core/Ac3Dec.h b/core/Ac3Dec.h new file mode 100644 index 000000000..a1ecaff66 --- /dev/null +++ b/core/Ac3Dec.h @@ -0,0 +1,15 @@ +/* $Id: Ac3Dec.h,v 1.1 2003/11/03 12:08:00 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_AC3_DEC_H +#define HB_AC3_DEC_H + +#include "HandBrakeInternal.h" + +HBAc3Dec * HBAc3DecInit( HBHandle *, HBAudio * ); +void HBAc3DecClose( HBAc3Dec ** ); + +#endif diff --git a/core/Ac3Decoder.cpp b/core/Ac3Decoder.cpp deleted file mode 100644 index 663184e40..000000000 --- a/core/Ac3Decoder.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* $Id: Ac3Decoder.cpp,v 1.21 2003/10/14 14:35:20 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 "Fifo.h" -#include "Manager.h" - -extern "C" { -#include <a52dec/a52.h> -} - -HBAc3Decoder::HBAc3Decoder( HBManager * manager, HBAudio * 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 ); - fAc3Frame->fSize = 0; - fAc3Buffer = NULL; - fPosInAc3Buffer = 0; - fRawBuffer = NULL; -} - -HBAc3Decoder::~HBAc3Decoder() -{ - if( fRawBuffer ) delete fRawBuffer; - if( fAc3Buffer ) delete fAc3Buffer; - delete fAc3Frame; - a52_free( fState ); - delete fLock; -} - -bool HBAc3Decoder::Work() -{ - if( !Lock() ) - { - return false; - } - - /* Push the latest decoded buffer */ - if( fRawBuffer ) - { - if( fAudio->fRawFifo->Push( fRawBuffer ) ) - { - fRawBuffer = NULL; - } - else - { - Unlock(); - return false; - } - } - - /* Get a frame header (7 bytes) */ - if( fAc3Frame->fSize < 7 ) - { - if( GetBytes( 7 ) ) - { - /* Get the size of the coming 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; - } - } - else - { - Unlock(); - return false; - } - } - - /* In case the audio should start later than the video, - insert some silence */ - if( fAudio->fDelay > 3 * 256 * 1000 / fAudio->fInSampleRate ) - { - 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; - - Unlock(); - return true; - } - - if( fAc3Frame->fSize >= 7 ) - { - /* Get the whole frame */ - if( GetBytes( (uint32_t) fFrameSize ) ) - { - /* Feed liba52 */ - a52_frame( fState, fAc3Frame->fData, &fOutFlags, - &fSampleLevel, 0 ); - fAc3Frame->fSize = 0; - - /* 6 blocks per frame, 256 samples per block */ - fRawBuffer = new HBBuffer( 12 * 256 * sizeof( float ) ); - fRawBuffer->fPosition = fPosition; - - sample_t * samples; - for( int i = 0; i < 6; i++ ) - { - /* Decode a block */ - a52_block( fState ); - - /* Get a pointer to the raw data */ - samples = a52_samples( fState ); - - /* Copy left channel data */ - memcpy( (float*) fRawBuffer->fData + i * 256, - samples, - 256 * sizeof( float ) ); - - /* Copy right channel data */ - memcpy( (float*) fRawBuffer->fData + ( 6 + i ) * 256, - samples + 256, - 256 * sizeof( float ) ); - } - } - else - { - Unlock(); - return false; - } - } - - Unlock(); - return true; -} - -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 - contains <size> bytes */ -bool HBAc3Decoder::GetBytes( uint32_t size ) -{ - while( fAc3Frame->fSize < size ) - { - if( !fAc3Buffer ) - { - if( !( fAc3Buffer = fAudio->fAc3Fifo->Pop() ) ) - { - return false; - } - fPosInAc3Buffer = 0; - fPosition = fAc3Buffer->fPosition; - } - - int willCopy = MIN( size - fAc3Frame->fSize, - fAc3Buffer->fSize - fPosInAc3Buffer ); - memcpy( fAc3Frame->fData + fAc3Frame->fSize, - fAc3Buffer->fData + fPosInAc3Buffer, - willCopy ); - fAc3Frame->fSize += willCopy; - fPosInAc3Buffer += willCopy; - - if( fAc3Buffer->fSize == fPosInAc3Buffer ) - { - delete fAc3Buffer; - fAc3Buffer = NULL; - } - } - - return true; -} diff --git a/core/Ac3Decoder.h b/core/Ac3Decoder.h deleted file mode 100644 index f63206b12..000000000 --- a/core/Ac3Decoder.h +++ /dev/null @@ -1,47 +0,0 @@ -/* $Id: Ac3Decoder.h,v 1.11 2003/10/14 14:35:20 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_AC3_DECODER_H -#define HB_AC3_DECODER_H - -#include "Common.h" - -class HBAc3Decoder -{ - public: - HBAc3Decoder( HBManager * manager, - HBAudio * audio ); - ~HBAc3Decoder(); - bool Work(); - - private: - 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 fPosInAc3Buffer; - HBBuffer * fRawBuffer; - - float fPosition; - int fFrameSize; -}; - -#endif diff --git a/core/AviMux.c b/core/AviMux.c new file mode 100644 index 000000000..bd0551217 --- /dev/null +++ b/core/AviMux.c @@ -0,0 +1,640 @@ +/* $Id: AviMux.c,v 1.5 2003/11/06 18:35:53 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "AviMux.h" +#include "Fifo.h" +#include "Thread.h" + +/* Local structures */ +typedef struct AviMainHeader AviMainHeader; +typedef struct AviStreamHeader AviStreamHeader; +typedef struct BitmapInfo BitmapInfo; +typedef struct WaveFormatEx WaveFormatEx; + +/* Local prototypes */ +static void AviMuxThread( void * ); +static void InitAviHeaders( HBAviMux * ); +static void AddChunk( HBAviMux *, HBBuffer **, uint32_t, + AviStreamHeader * ); +static void AddIndex( HBAviMux * ); +static void WriteInt8( FILE *, uint8_t ); +static void WriteInt16( FILE *, uint16_t ); +static void WriteInt32( FILE *, uint32_t ); +static void WriteBuffer( FILE *, HBBuffer * ); +static void WriteMainHeader( FILE *, AviMainHeader * ); +static void WriteStreamHeader( FILE *, AviStreamHeader * ); +static void WriteBitmapInfo( FILE *, BitmapInfo * ); +static void WriteWaveFormatEx( FILE *, WaveFormatEx * ); +static void IndexAddInt32( HBBuffer * buffer, uint32_t ); +static HBBuffer * Pop( HBAviMux *, HBFifo * ); + +#define AVIF_HASINDEX 0x10 +#define AVIIF_KEYFRAME 0x10 +#define FOURCC(a) ((a[3]<<24)|(a[2]<<16)|(a[1]<<8)|a[0]) + +/* Structures definitions */ +struct __attribute__((__packed__)) AviMainHeader +{ + uint32_t FourCC; + uint32_t BytesCount; + uint32_t MicroSecPerFrame; + uint32_t MaxBytesPerSec; + uint32_t PaddingGranularity; + uint32_t Flags; + uint32_t TotalFrames; + uint32_t InitialFrames; + uint32_t Streams; + uint32_t SuggestedBufferSize; + uint32_t Width; + uint32_t Height; + uint32_t Reserved[4]; +}; + +struct __attribute__((__packed__)) AviStreamHeader +{ + uint32_t FourCC; + uint32_t BytesCount; + uint32_t Type; + uint32_t Handler; + uint32_t Flags; + uint16_t Priority; + uint16_t Language; + uint32_t InitialFrames; + uint32_t Scale; + uint32_t Rate; + uint32_t Start; + uint32_t Length; + uint32_t SuggestedBufferSize; + uint32_t Quality; + uint32_t SampleSize; + int16_t Left; + int16_t Top; + int16_t Right; + int16_t Bottom; +}; + +struct __attribute__((__packed__)) BitmapInfo +{ + uint32_t FourCC; + uint32_t BytesCount; + uint32_t Size; + uint32_t Width; + uint32_t Height; + uint16_t Planes; + uint16_t BitCount; + uint32_t Compression; + uint32_t SizeImage; + uint32_t XPelsPerMeter; + uint32_t YPelsPerMeter; + uint32_t ClrUsed; + uint32_t ClrImportant; + uint8_t Blue; + uint8_t Green; + uint8_t Red; + uint8_t Reserved; +}; + +struct __attribute__((__packed__)) WaveFormatEx +{ + uint32_t FourCC; + uint32_t BytesCount; + uint16_t FormatTag; + uint16_t Channels; + uint32_t SamplesPerSec; + uint32_t AvgBytesPerSec; + uint16_t BlockAlign; + uint16_t BitsPerSample; + uint16_t Size; + + /* mp3 specific */ + uint16_t Id; + uint32_t Flags; + uint16_t BlockSize; + uint16_t FramesPerBlock; + uint16_t CodecDelay; +}; + +struct HBAviMux +{ + HBHandle * handle; + HBTitle * title; + HBAudio * audio; + HBAudio * optAudio; + + AviMainHeader mainHeader; + AviStreamHeader videoHeader; + BitmapInfo videoFormat; + AviStreamHeader audioHeader; + WaveFormatEx audioFormat; + AviStreamHeader optAudioHeader; + WaveFormatEx optAudioFormat; + + /* Data size in bytes, not including headers */ + unsigned size; + FILE * file; + HBBuffer * index; + + int die; + HBThread * thread; +}; + +HBAviMux * HBAviMuxInit( HBHandle * handle, HBTitle * title, + HBAudio * audio, HBAudio * optAudio ) +{ + HBAviMux * a; + if( !( a = malloc( sizeof( HBAviMux ) ) ) ) + { + HBLog( "HBAviMuxInit: malloc() failed, gonna crash" ); + return NULL; + } + + a->handle = handle; + a->title = title; + a->audio = audio; + a->optAudio = optAudio; + + a->size = 0; + a->file = NULL; + a->index = HBBufferInit( 1024 * 1024 ); + a->index->size = 0; + + a->die = 0; + a->thread = HBThreadInit( "avi muxer", AviMuxThread, a, + HB_NORMAL_PRIORITY ); + return a; +} + +void HBAviMuxClose( HBAviMux ** _a ) +{ + HBAviMux * a = *_a; + + a->die = 1; + HBThreadClose( &a->thread ); + free( a ); + + *_a = NULL; +} + +static void AviMuxThread( void * _a ) +{ + HBAviMux * a = (HBAviMux*) _a; + HBTitle * title = a->title; + HBAudio * audio = a->audio; + HBAudio * optAudio = a->optAudio; + + HBBuffer * videoBuffer = NULL; + HBBuffer * audioBuffer = NULL; + HBBuffer * optAudioBuffer = NULL; + + /* Open destination file */ + HBLog( "HBAviMux: opening %s", title->file ); + if( !( a->file = fopen( title->file, "w" ) ) ) + { + HBLog( "HBAviMux: fopen() failed" ); + HBErrorOccured( a->handle, HB_ERROR_AVI_WRITE ); + return; + } + + /* Get a buffer for each track */ + videoBuffer = Pop( a, title->mpeg4Fifo ); + audioBuffer = Pop( a, audio->mp3Fifo ); + if( optAudio ) + { + optAudioBuffer = Pop( a, optAudio->mp3Fifo ); + } + + /* Failed ? Then forget it */ + if( !videoBuffer || !audioBuffer || + ( optAudio && !optAudioBuffer ) ) + { + fclose( a->file ); + a->file = NULL; + + HBLog( "HBAviMux: deleting %s", title->file ); + unlink( title->file ); + return; + } + + InitAviHeaders( a ); + + for( ;; ) + { + /* Get a buffer for each track */ + if( !videoBuffer ) + { + videoBuffer = Pop( a, title->mpeg4Fifo ); + } + if( !audioBuffer ) + { + audioBuffer = Pop( a, audio->mp3Fifo ); + } + if( optAudio && !optAudioBuffer ) + { + optAudioBuffer = Pop( a, optAudio->mp3Fifo ); + } + + if( !videoBuffer && !audioBuffer && !optAudioBuffer ) + { + /* Couldn't get anything -> must exit NOW */ + break; + } + + /* Interleave frames in the same order than they were in the + original MPEG stream */ + if( videoBuffer && + ( !audioBuffer || + videoBuffer->position < audioBuffer->position ) && + ( !optAudioBuffer || + videoBuffer->position < optAudioBuffer->position ) ) + { + AddChunk( a, &videoBuffer, FOURCC( "00dc" ), + &a->videoHeader ); + } + else if( audioBuffer && + ( !optAudioBuffer || + audioBuffer->position < optAudioBuffer->position ) ) + { + AddChunk( a, &audioBuffer, FOURCC( "01wb" ), + &a->audioHeader ); + } + else + { + AddChunk( a, &optAudioBuffer, FOURCC( "02wb" ), + &a->optAudioHeader ); + } + } + + AddIndex( a ); + + HBLog( "HBAviMux: closing %s", title->file ); + fclose( a->file ); +} + +static void InitAviHeaders( HBAviMux * a ) +{ + HBTitle * title = a->title; + HBAudio * audio = a->audio; + HBAudio * optAudio = a->optAudio; + AviMainHeader * mainHeader = &a->mainHeader; + AviStreamHeader * videoHeader = &a->videoHeader; + BitmapInfo * videoFormat = &a->videoFormat; + AviStreamHeader * audioHeader = &a->audioHeader; + WaveFormatEx * audioFormat = &a->audioFormat; + AviStreamHeader * optAudioHeader = &a->optAudioHeader; + WaveFormatEx * optAudioFormat = &a->optAudioFormat; + FILE * file = a->file; + int hdrlBytes; + int i; + + /* AVI main header */ + memset( mainHeader, 0, sizeof( AviMainHeader ) ); + mainHeader->FourCC = FOURCC( "avih" ); + mainHeader->BytesCount = sizeof( AviMainHeader ) - 8; + mainHeader->MicroSecPerFrame = (uint64_t) 1000000 * + title->rateBase / title->rate; + mainHeader->Streams = optAudio ? 3 : 2; + mainHeader->Width = title->outWidth; + mainHeader->Height = title->outHeight; + + /* Video stream header */ + memset( videoHeader, 0, sizeof( AviStreamHeader ) ); + videoHeader->FourCC = FOURCC( "strh" ); + videoHeader->BytesCount = sizeof( AviStreamHeader ) - 8; + videoHeader->Type = FOURCC( "vids" ); + + if( title->codec == HB_CODEC_FFMPEG ) + videoHeader->Handler = FOURCC( "divx" ); + else if( title->codec == HB_CODEC_XVID ) + videoHeader->Handler = FOURCC( "xvid" ); + + videoHeader->Scale = title->rateBase; + videoHeader->Rate = title->rate; + + /* Video stream format */ + memset( videoFormat, 0, sizeof( BitmapInfo ) ); + videoFormat->FourCC = FOURCC( "strf" ); + videoFormat->BytesCount = sizeof( BitmapInfo ) - 8; + videoFormat->Size = sizeof( BitmapInfo ) - 8; + videoFormat->Width = title->outWidth; + videoFormat->Height = title->outHeight; + videoFormat->Planes = 1; + videoFormat->BitCount = 24; + if( title->codec == HB_CODEC_FFMPEG ) + videoFormat->Compression = FOURCC( "DX50" ); + else if( title->codec == HB_CODEC_XVID ) + videoFormat->Compression = FOURCC( "XVID" ); + + /* Audio stream header */ + memset( audioHeader, 0, sizeof( AviStreamHeader ) ); + audioHeader->FourCC = FOURCC( "strh" ); + audioHeader->BytesCount = sizeof( AviStreamHeader ) - 8; + audioHeader->Type = FOURCC( "auds" ); + audioHeader->InitialFrames = 1; + audioHeader->Scale = 1152; + audioHeader->Rate = audio->outSampleRate; + audioHeader->Quality = 0xFFFFFFFF; + + /* Audio stream format */ + memset( audioFormat, 0, sizeof( WaveFormatEx ) ); + audioFormat->FourCC = FOURCC( "strf" ); + audioFormat->BytesCount = sizeof( WaveFormatEx ) - 8; + audioFormat->FormatTag = 0x55; + audioFormat->Channels = 2; + audioFormat->SamplesPerSec = audio->outSampleRate; + audioFormat->AvgBytesPerSec = audio->outBitrate * 1024 / 8; + audioFormat->BlockAlign = 1152; + audioFormat->Size = 12; + audioFormat->Id = 1; + audioFormat->Flags = 2; + audioFormat->BlockSize = 1152; + audioFormat->FramesPerBlock = 1; + audioFormat->CodecDelay = 1393; + + if( optAudio ) + { + /* optAudio stream header */ + memset( optAudioHeader, 0, sizeof( AviStreamHeader ) ); + optAudioHeader->FourCC = FOURCC( "strh" ); + optAudioHeader->BytesCount = sizeof( AviStreamHeader ) - 8; + optAudioHeader->Type = FOURCC( "auds" ); + optAudioHeader->InitialFrames = 1; + optAudioHeader->Scale = 1152; + optAudioHeader->Rate = optAudio->outSampleRate; + optAudioHeader->Quality = 0xFFFFFFFF; + + /* optAudio stream format */ + memset( optAudioFormat, 0, sizeof( WaveFormatEx ) ); + optAudioFormat->FourCC = FOURCC( "strf" ); + optAudioFormat->BytesCount = sizeof( WaveFormatEx ) - 8; + optAudioFormat->FormatTag = 0x55; + optAudioFormat->Channels = 2; + optAudioFormat->SamplesPerSec = optAudio->outSampleRate; + optAudioFormat->AvgBytesPerSec = optAudio->outBitrate * 1024 / 8; + optAudioFormat->BlockAlign = 1152; + optAudioFormat->Size = 12; + optAudioFormat->Id = 1; + optAudioFormat->Flags = 2; + optAudioFormat->BlockSize = 1152; + optAudioFormat->FramesPerBlock = 1; + optAudioFormat->CodecDelay = 1393; + } + + hdrlBytes = 4 + sizeof( AviMainHeader ) + + ( optAudio ? 3 : 2 ) * ( 12 + sizeof( AviStreamHeader ) ) + + sizeof( BitmapInfo ) + + ( optAudio ? 2 : 1 ) * sizeof( WaveFormatEx ); + + /* Here we really start to write into the file */ + + WriteInt32( file, FOURCC( "RIFF" ) ); + WriteInt32( file, 2040 ); + WriteInt32( file, FOURCC( "AVI " ) ); + WriteInt32( file, FOURCC( "LIST" ) ); + WriteInt32( file, hdrlBytes ); + WriteInt32( file, FOURCC( "hdrl" ) ); + WriteMainHeader( file, mainHeader ); + WriteInt32( file, FOURCC( "LIST" ) ); + WriteInt32( file, 4 + sizeof( AviStreamHeader ) + + sizeof( BitmapInfo ) ); + WriteInt32( file, FOURCC( "strl" ) ); + WriteStreamHeader( file, videoHeader ); + WriteBitmapInfo( file, videoFormat ); + WriteInt32( file, FOURCC( "LIST" ) ); + WriteInt32( file, 4 + sizeof( AviStreamHeader ) + + sizeof( WaveFormatEx ) ); + WriteInt32( file, FOURCC( "strl" ) ); + WriteStreamHeader( file, audioHeader ); + WriteWaveFormatEx( file, audioFormat ); + if( optAudio ) + { + WriteInt32( file, FOURCC( "LIST" ) ); + WriteInt32( file, 4 + sizeof( AviStreamHeader ) + + sizeof( WaveFormatEx ) ); + WriteInt32( file, FOURCC( "strl" ) ); + WriteStreamHeader( file, optAudioHeader ); + WriteWaveFormatEx( file, optAudioFormat ); + } + WriteInt32( file, FOURCC( "JUNK" ) ); + WriteInt32( file, 2008 - hdrlBytes ); + for( i = 0; i < 2008 - hdrlBytes; i++ ) + { + WriteInt8( file, 0 ); + } + WriteInt32( file, FOURCC( "LIST" ) ); + WriteInt32( file, 4 ); + WriteInt32( file, FOURCC( "movi" ) ); +} + +static void AddChunk( HBAviMux * a, HBBuffer ** _buffer, + uint32_t fourCC, AviStreamHeader * header ) +{ + HBBuffer * buffer = *_buffer; + + /* Update index */ + IndexAddInt32( a->index, fourCC ); + IndexAddInt32( a->index, buffer->keyFrame ? AVIIF_KEYFRAME : 0 ); + IndexAddInt32( a->index, 4 + a->size ); + IndexAddInt32( a->index, buffer->size ); + + /* Write the chunk to the file */ + fseek( a->file, 0, SEEK_END ); + WriteInt32( a->file, fourCC ); + WriteInt32( a->file, buffer->size ); + WriteBuffer( a->file, buffer ); + + /* Chunks must be 2-bytes aligned */ + if( buffer->size & 1 ) + { + WriteInt8( a->file, 0 ); + } + + /* Update headers */ + a->size += 8 + EVEN( buffer->size ); + header->Length++; + + /* RIFF size */ + fseek( a->file, 4, SEEK_SET ); + WriteInt32( a->file, 2040 + a->size ); + + /* AviStreamHeader's length */ + fseek( a->file, 140, SEEK_SET ); + WriteInt32( a->file, a->videoHeader.Length ); + fseek( a->file, 268, SEEK_SET ); + WriteInt32( a->file, a->audioHeader.Length ); + if( a->optAudio ) + { + fseek( a->file, 382, SEEK_SET ); + WriteInt32( a->file, a->optAudioHeader.Length ); + } + + /* movi size */ + fseek( a->file, 2040, SEEK_SET ); + WriteInt32( a->file, 4 + a->size ); + + HBBufferClose( _buffer ); +} + +static void AddIndex( HBAviMux * a ) +{ + fseek( a->file, 0, SEEK_END ); + + WriteInt32( a->file, FOURCC( "idx1" ) ); + WriteInt32( a->file, a->index->size ); + WriteBuffer( a->file, a->index ); + + a->size += 8 + a->index->size; + fseek( a->file, 4, SEEK_SET ); + WriteInt32( a->file, 2040 + a->size ); + a->mainHeader.Flags |= AVIF_HASINDEX; + fseek( a->file, 24, SEEK_SET ); + WriteMainHeader( a->file, &a->mainHeader ); +} + +static void WriteInt8( FILE * file, uint8_t val ) +{ + fputc( val, file ); +} + +static void WriteInt16( FILE * file, uint16_t val ) +{ + fputc( val & 0xFF, file ); + fputc( val >> 8, file ); +} + +static void WriteInt32( FILE * file, uint32_t val ) +{ + fputc( val & 0xFF, file ); + fputc( ( val >> 8 ) & 0xFF, file ); + fputc( ( val >> 16 ) & 0xFF, file ); + fputc( val >> 24, file ); +} + +static void WriteBuffer( FILE * file, HBBuffer * buffer ) +{ + fwrite( buffer->data, buffer->size, 1, file ); +} + +static void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo ) +{ + WriteInt32( file, bitmapInfo->FourCC ); + WriteInt32( file, bitmapInfo->BytesCount ); + WriteInt32( file, bitmapInfo->Size ); + WriteInt32( file, bitmapInfo->Width ); + WriteInt32( file, bitmapInfo->Height ); + WriteInt16( file, bitmapInfo->Planes ); + WriteInt16( file, bitmapInfo->BitCount ); + WriteInt32( file, bitmapInfo->Compression ); + WriteInt32( file, bitmapInfo->SizeImage ); + WriteInt32( file, bitmapInfo->XPelsPerMeter ); + WriteInt32( file, bitmapInfo->YPelsPerMeter ); + WriteInt32( file, bitmapInfo->ClrUsed ); + WriteInt32( file, bitmapInfo->ClrImportant ); + WriteInt8( file, bitmapInfo->Blue ); + WriteInt8( file, bitmapInfo->Green ); + WriteInt8( file, bitmapInfo->Red ); + WriteInt8( file, bitmapInfo->Reserved ); +} + +static void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx ) +{ + WriteInt32( file, waveFormatEx->FourCC ); + WriteInt32( file, waveFormatEx->BytesCount ); + WriteInt16( file, waveFormatEx->FormatTag ); + WriteInt16( file, waveFormatEx->Channels ); + WriteInt32( file, waveFormatEx->SamplesPerSec ); + WriteInt32( file, waveFormatEx->AvgBytesPerSec ); + WriteInt16( file, waveFormatEx->BlockAlign ); + WriteInt16( file, waveFormatEx->BitsPerSample ); + WriteInt16( file, waveFormatEx->Size ); + WriteInt16( file, waveFormatEx->Id ); + WriteInt32( file, waveFormatEx->Flags ); + WriteInt16( file, waveFormatEx->BlockSize ); + WriteInt16( file, waveFormatEx->FramesPerBlock ); + WriteInt16( file, waveFormatEx->CodecDelay ); +} + +static void WriteMainHeader( FILE * file, AviMainHeader * mainHeader ) +{ + WriteInt32( file, mainHeader->FourCC ); + WriteInt32( file, mainHeader->BytesCount ); + WriteInt32( file, mainHeader->MicroSecPerFrame ); + WriteInt32( file, mainHeader->MaxBytesPerSec ); + WriteInt32( file, mainHeader->PaddingGranularity ); + WriteInt32( file, mainHeader->Flags ); + WriteInt32( file, mainHeader->TotalFrames ); + WriteInt32( file, mainHeader->InitialFrames ); + WriteInt32( file, mainHeader->Streams ); + WriteInt32( file, mainHeader->SuggestedBufferSize ); + WriteInt32( file, mainHeader->Width ); + WriteInt32( file, mainHeader->Height ); + WriteInt32( file, mainHeader->Reserved[0] ); + WriteInt32( file, mainHeader->Reserved[1] ); + WriteInt32( file, mainHeader->Reserved[2] ); + WriteInt32( file, mainHeader->Reserved[3] ); +} + +static void WriteStreamHeader( FILE * file, AviStreamHeader * streamHeader ) +{ + WriteInt32( file, streamHeader->FourCC ); + WriteInt32( file, streamHeader->BytesCount ); + WriteInt32( file, streamHeader->Type ); + WriteInt32( file, streamHeader->Handler ); + WriteInt32( file, streamHeader->Flags ); + WriteInt16( file, streamHeader->Priority ); + WriteInt16( file, streamHeader->Language ); + WriteInt32( file, streamHeader->InitialFrames ); + WriteInt32( file, streamHeader->Scale ); + WriteInt32( file, streamHeader->Rate ); + WriteInt32( file, streamHeader->Start ); + WriteInt32( file, streamHeader->Length ); + WriteInt32( file, streamHeader->SuggestedBufferSize ); + WriteInt32( file, streamHeader->Quality ); + WriteInt32( file, streamHeader->SampleSize ); + WriteInt16( file, streamHeader->Left ); + WriteInt16( file, streamHeader->Top ); + WriteInt16( file, streamHeader->Right ); + WriteInt16( file, streamHeader->Bottom ); +} + +static void IndexAddInt32( HBBuffer * b, uint32_t val ) +{ + if( b->size + 16 > b->alloc ) + { + HBLog( "HBAviMux: reallocing index (%d MB)", + 1 + b->alloc / 1024 / 1024 ); + HBBufferReAlloc( b, b->alloc + 1024 + 1024 ); + } + + b->data[b->size++] = val & 0xFF; + b->data[b->size++] = ( val >> 8 ) & 0xFF; + b->data[b->size++] = ( val >> 16 ) & 0xFF; + b->data[b->size++] = val >> 24; +} + +static HBBuffer * Pop( HBAviMux * a, HBFifo * fifo ) +{ + HBBuffer * buffer; + + for( ;; ) + { + HBCheckPaused( a->handle ); + + if( ( buffer = HBFifoPop( fifo ) ) ) + { + return buffer; + } + + if( a->die ) + { + break; + } + + HBSnooze( 10000 ); + } + + return NULL; +} + diff --git a/core/AviMux.h b/core/AviMux.h new file mode 100644 index 000000000..1fccbe971 --- /dev/null +++ b/core/AviMux.h @@ -0,0 +1,15 @@ +/* $Id: AviMux.h,v 1.1 2003/11/03 12:08:00 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_AVI_MUX_H +#define HB_AVI_MUX_H + +#include "HandBrakeInternal.h" + +HBAviMux * HBAviMuxInit( HBHandle *, HBTitle *, HBAudio *, HBAudio * ); +void HBAviMuxClose( HBAviMux ** ); + +#endif diff --git a/core/AviMuxer.cpp b/core/AviMuxer.cpp deleted file mode 100644 index 4a84fe8b8..000000000 --- a/core/AviMuxer.cpp +++ /dev/null @@ -1,481 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#include "AviMuxer.h" -#include "Manager.h" - -#define AVIF_HASINDEX 0x10 -#define AVIIF_KEYFRAME 0x10 - -#define FOURCC(a) ( ( a[3] << 24 ) | ( a[2] << 16 ) | ( a[1] << 8 ) | a[0] ) - -/* TODO : check return values from fputc/fwrite in case disk is full - or something */ - -void WriteInt8( FILE * file, uint8_t val ) -{ - fputc( val, file ); -} - -void WriteInt16( FILE * file, uint16_t val ) -{ - fputc( val & 0xFF, file ); - fputc( val >> 8, file ); -} - -void WriteInt32( FILE * file, uint32_t val ) -{ - fputc( val & 0xFF, file ); - fputc( ( val >> 8 ) & 0xFF, file ); - fputc( ( val >> 16 ) & 0xFF, file ); - fputc( val >> 24, file ); -} - -void WriteBuffer( FILE * file, HBBuffer * buffer ) -{ - fwrite( buffer->fData, buffer->fSize, 1, file ); -} - -void WriteBitmapInfo( FILE * file, BitmapInfo * bitmapInfo ) -{ - WriteInt32( file, bitmapInfo->FourCC ); - WriteInt32( file, bitmapInfo->BytesCount ); - WriteInt32( file, bitmapInfo->Size ); - WriteInt32( file, bitmapInfo->Width ); - WriteInt32( file, bitmapInfo->Height ); - WriteInt16( file, bitmapInfo->Planes ); - WriteInt16( file, bitmapInfo->BitCount ); - WriteInt32( file, bitmapInfo->Compression ); - WriteInt32( file, bitmapInfo->SizeImage ); - WriteInt32( file, bitmapInfo->XPelsPerMeter ); - WriteInt32( file, bitmapInfo->YPelsPerMeter ); - WriteInt32( file, bitmapInfo->ClrUsed ); - WriteInt32( file, bitmapInfo->ClrImportant ); - WriteInt8( file, bitmapInfo->Blue ); - WriteInt8( file, bitmapInfo->Green ); - WriteInt8( file, bitmapInfo->Red ); - WriteInt8( file, bitmapInfo->Reserved ); -} - -void WriteWaveFormatEx( FILE * file, WaveFormatEx * waveFormatEx ) -{ - WriteInt32( file, waveFormatEx->FourCC ); - WriteInt32( file, waveFormatEx->BytesCount ); - WriteInt16( file, waveFormatEx->FormatTag ); - WriteInt16( file, waveFormatEx->Channels ); - WriteInt32( file, waveFormatEx->SamplesPerSec ); - WriteInt32( file, waveFormatEx->AvgBytesPerSec ); - WriteInt16( file, waveFormatEx->BlockAlign ); - WriteInt16( file, waveFormatEx->BitsPerSample ); - WriteInt16( file, waveFormatEx->Size ); - WriteInt16( file, waveFormatEx->Id ); - WriteInt32( file, waveFormatEx->Flags ); - WriteInt16( file, waveFormatEx->BlockSize ); - WriteInt16( file, waveFormatEx->FramesPerBlock ); - WriteInt16( file, waveFormatEx->CodecDelay ); -} - -void WriteMainHeader( FILE * file, AviMainHeader * mainHeader ) -{ - WriteInt32( file, mainHeader->FourCC ); - WriteInt32( file, mainHeader->BytesCount ); - WriteInt32( file, mainHeader->MicroSecPerFrame ); - WriteInt32( file, mainHeader->MaxBytesPerSec ); - WriteInt32( file, mainHeader->PaddingGranularity ); - WriteInt32( file, mainHeader->Flags ); - WriteInt32( file, mainHeader->TotalFrames ); - WriteInt32( file, mainHeader->InitialFrames ); - WriteInt32( file, mainHeader->Streams ); - WriteInt32( file, mainHeader->SuggestedBufferSize ); - WriteInt32( file, mainHeader->Width ); - WriteInt32( file, mainHeader->Height ); - WriteInt32( file, mainHeader->Reserved[0] ); - WriteInt32( file, mainHeader->Reserved[1] ); - WriteInt32( file, mainHeader->Reserved[2] ); - WriteInt32( file, mainHeader->Reserved[3] ); -} - -void WriteStreamHeader( FILE * file, AviStreamHeader * streamHeader ) -{ - WriteInt32( file, streamHeader->FourCC ); - WriteInt32( file, streamHeader->BytesCount ); - WriteInt32( file, streamHeader->Type ); - WriteInt32( file, streamHeader->Handler ); - WriteInt32( file, streamHeader->Flags ); - WriteInt16( file, streamHeader->Priority ); - WriteInt16( file, streamHeader->Language ); - WriteInt32( file, streamHeader->InitialFrames ); - WriteInt32( file, streamHeader->Scale ); - WriteInt32( file, streamHeader->Rate ); - WriteInt32( file, streamHeader->Start ); - WriteInt32( file, streamHeader->Length ); - WriteInt32( file, streamHeader->SuggestedBufferSize ); - WriteInt32( file, streamHeader->Quality ); - WriteInt32( file, streamHeader->SampleSize ); - WriteInt16( file, streamHeader->Left ); - WriteInt16( file, streamHeader->Top ); - WriteInt16( file, streamHeader->Right ); - WriteInt16( file, streamHeader->Bottom ); -} - -HBAviIndex::HBAviIndex( uint32_t size ) - : HBBuffer( size ) -{ - fSize = 0; -} - -void HBAviIndex::WriteInt32( uint32_t val ) -{ - if( fSize + 16 > fAllocSize ) - { - /* Realloc if needed */ - Log( "HBAviIndex::WriteInt32() : reallocing index (%d -> %d MB)", - fAllocSize / ( 1024 * 1024 ), - 1 + fAllocSize / ( 1024 * 1024 ) ); - ReAlloc( fAllocSize + 1024 * 1024 ); - } - - fData[fSize] = val & 0xFF; - fData[fSize + 1] = ( val >> 8 ) & 0xFF; - fData[fSize + 2] = ( val >> 16 ) & 0xFF; - fData[fSize + 3] = val >> 24; - - fSize += 4; -} - -HBAviMuxer::HBAviMuxer( HBManager * manager, HBTitle * title, - HBAudio * audio1, HBAudio * audio2, - char * fileName ) - : HBThread( "avimuxer", HB_NORMAL_PRIORITY ) -{ - fManager = manager; - fTitle = title; - fAudio1 = audio1; - fAudio2 = audio2; - fFileName = strdup( fileName ); - - fVideoBuffer = NULL; - fAudio1Buffer = NULL; - fAudio2Buffer = NULL; - - fRiffBytesCount = 2040; - fMoviBytesCount = 4; - - Run(); -} - -void HBAviMuxer::DoWork() -{ - /* Open the destination file */ - if( !( fFile = fopen( fFileName, "w" ) ) ) - { - Log( "HBAviMuxer: fopen failed" ); - fManager->Error( HB_ERROR_AVI_WRITE ); - return; - } - - /* Initializations */ - memset( &fMainHeader, 0, sizeof( AviMainHeader ) ); - memset( &fVideoStreamHeader, 0, sizeof( AviStreamHeader ) ); - memset( &fAudio1StreamHeader, 0, sizeof( AviStreamHeader ) ); - memset( &fAudio2StreamHeader, 0, sizeof( AviStreamHeader ) ); - memset( &fVideoStreamFormat, 0, sizeof( BitmapInfo ) ); - memset( &fAudio1StreamFormat, 0, sizeof( WaveFormatEx ) ); - memset( &fAudio2StreamFormat, 0, sizeof( WaveFormatEx ) ); - - /* Alloc an 1 MB index (to be realloced later if needed) */ - fIndex = new HBAviIndex( 1024 * 1024 ); - - /* Main loop */ - for( ;; ) - { - while( fSuspend ) - { - Snooze( 10000 ); - } - - if( !fVideoBuffer ) - { - fVideoBuffer = Pop( fTitle->fMpeg4Fifo ); - } - if( fAudio1 && !fAudio1Buffer ) - { - fAudio1Buffer = Pop( fAudio1->fMp3Fifo ); - } - if( fAudio2 && !fAudio2Buffer ) - { - fAudio2Buffer = Pop( fAudio2->fMp3Fifo ); - } - - if( !fVideoBuffer && !fAudio1Buffer && !fAudio2Buffer ) - { - break; - } - - if( fVideoBuffer && - ( !fAudio1Buffer || - fVideoBuffer->fPosition < fAudio1Buffer->fPosition ) && - ( !fAudio2Buffer || - fVideoBuffer->fPosition < fAudio2Buffer->fPosition ) ) - { - AddVideoChunk(); - } - else if( fAudio1Buffer && - ( !fAudio2Buffer || - fAudio1Buffer->fPosition < fAudio2Buffer->fPosition ) ) - { - AddAudioChunk( 1 ); - } - else - { - AddAudioChunk( 2 ); - } - } - - /* Write the index */ - fseek( fFile, 0, SEEK_END ); - WriteInt32( fFile, FOURCC( "idx1" ) ); - WriteInt32( fFile, fIndex->fSize ); - WriteBuffer( fFile, fIndex ); - - /* Update the headers */ - fRiffBytesCount += 8 + fIndex->fSize; - fMainHeader.Flags |= AVIF_HASINDEX; - UpdateMainHeader(); - - delete fIndex; - - fclose( fFile ); -} - -bool HBAviMuxer::AddVideoChunk() -{ - fRiffBytesCount += 8 + EVEN( fVideoBuffer->fSize ); - fMoviBytesCount += 8 + EVEN( fVideoBuffer->fSize ); - - fMainHeader.MicroSecPerFrame = 1000000 * (uint64_t) fTitle->fScale / - fTitle->fRate; - fMainHeader.TotalFrames++; - fMainHeader.Width = fTitle->fOutWidth; - fMainHeader.Height = fTitle->fOutHeight; - - fVideoStreamHeader.FourCC = FOURCC( "strh" ); - fVideoStreamHeader.BytesCount = AVI_STREAM_HEADER_SIZE - 8; - fVideoStreamHeader.Type = FOURCC( "vids" ); - fVideoStreamHeader.Handler = FOURCC( "DIVX" ); - fVideoStreamHeader.Scale = fTitle->fScale; - fVideoStreamHeader.Rate = fTitle->fRate; - fVideoStreamHeader.Length++; - - fVideoStreamFormat.FourCC = FOURCC( "strf" ); - fVideoStreamFormat.BytesCount = BITMAP_INFO_SIZE - 8; - fVideoStreamFormat.Size = BITMAP_INFO_SIZE - 8; - fVideoStreamFormat.Width = fTitle->fOutWidth; - fVideoStreamFormat.Height = fTitle->fOutHeight; - fVideoStreamFormat.Planes = 1; - fVideoStreamFormat.BitCount = 24; - fVideoStreamFormat.Compression = FOURCC( "DIVX" );; - - UpdateMainHeader(); - - fseek( fFile, 0, SEEK_END ); - - /* Update the index */ - fIndex->WriteInt32( FOURCC( "00dc" ) ); - fIndex->WriteInt32( fVideoBuffer->fKeyFrame ? AVIIF_KEYFRAME : 0 ); - fIndex->WriteInt32( ftell( fFile ) - 2044 ); - fIndex->WriteInt32( fVideoBuffer->fSize ); - - /* Write the chunk */ - WriteInt32( fFile, FOURCC( "00dc" ) ); - WriteInt32( fFile, fVideoBuffer->fSize ); - WriteBuffer( fFile, fVideoBuffer ); - - /* Chunks must be 2-bytes aligned */ - if( fVideoBuffer->fSize & 1 ) - { - WriteInt8( fFile, 0 ); - } - - delete fVideoBuffer; - fVideoBuffer = NULL; - - return true; -} - -bool HBAviMuxer::AddAudioChunk( int track ) -{ - HBAudio * info; - HBBuffer * buffer; - AviStreamHeader * streamHeader; - WaveFormatEx * streamFormat; - - if( track == 1 ) - { - info = fAudio1; - buffer = fAudio1Buffer; - streamHeader = &fAudio1StreamHeader; - streamFormat = &fAudio1StreamFormat; - } - else - { - info = fAudio2; - buffer = fAudio2Buffer; - streamHeader = &fAudio2StreamHeader; - streamFormat = &fAudio2StreamFormat; - } - - fRiffBytesCount += 8 + EVEN( buffer->fSize ); - fMoviBytesCount += 8 + EVEN( buffer->fSize ); - - streamHeader->FourCC = FOURCC( "strh" ); - streamHeader->BytesCount = AVI_STREAM_HEADER_SIZE - 8; - streamHeader->Type = FOURCC( "auds" ); - streamHeader->InitialFrames = 1; - streamHeader->Scale = 1152; - streamHeader->Rate = info->fOutSampleRate; - streamHeader->Length++; - streamHeader->Quality = 0xFFFFFFFF; - - - streamFormat->FourCC = FOURCC( "strf" ); - streamFormat->BytesCount = WAVE_FORMAT_EX_SIZE - 8; - streamFormat->FormatTag = 0x55; - streamFormat->Channels = 2; - streamFormat->SamplesPerSec = info->fOutSampleRate; - streamFormat->AvgBytesPerSec = info->fOutBitrate * 1024 / 8; - streamFormat->BlockAlign = 1152; - - /* stolen from libavformat/wav.c */ - streamFormat->Size = 12; - streamFormat->Id = 1; - streamFormat->Flags = 2; - streamFormat->BlockSize = 1152; - streamFormat->FramesPerBlock = 1; - streamFormat->CodecDelay = 1393; - - UpdateMainHeader(); - - fseek( fFile, 0, SEEK_END ); - - /* Update the index */ - if( track == 1 ) - { - fIndex->WriteInt32( FOURCC( "01wb" ) ); - } - else - { - fIndex->WriteInt32( FOURCC( "02wb" ) ); - } - fIndex->WriteInt32( buffer->fKeyFrame ? AVIIF_KEYFRAME : 0 ); - fIndex->WriteInt32( ftell( fFile ) - 2044 ); - fIndex->WriteInt32( buffer->fSize ); - - /* Write the chunk */ - WriteInt32( fFile, - ( track == 1 ) ? FOURCC( "01wb" ) : FOURCC( "02wb" ) ); - WriteInt32( fFile, buffer->fSize ); - WriteBuffer( fFile, buffer ); - - /* Chunks must be 2-bytes aligned */ - if( buffer->fSize & 1 ) - { - WriteInt8( fFile, 0 ); - } - - delete buffer; - if( track == 1 ) - { - fAudio1Buffer = NULL; - } - else - { - fAudio2Buffer = NULL; - } - - return true; -} - -void HBAviMuxer::UpdateMainHeader() -{ - fMainHeader.FourCC = FOURCC( "avih" ); - fMainHeader.BytesCount = AVI_MAIN_HEADER_SIZE - 8; - fMainHeader.Streams = 1 + ( fAudio1 ? 1 : 0 ) + - ( fAudio2 ? 1 : 0 ); - - fHdrlBytesCount = 4 + AVI_MAIN_HEADER_SIZE + 12 + - AVI_STREAM_HEADER_SIZE + BITMAP_INFO_SIZE; - - if( fAudio1 ) - { - fHdrlBytesCount += 12 + AVI_STREAM_HEADER_SIZE + - WAVE_FORMAT_EX_SIZE; - } - if( fAudio2 ) - { - fHdrlBytesCount += 12 + AVI_STREAM_HEADER_SIZE + - WAVE_FORMAT_EX_SIZE; - } - - fseek( fFile, 0, SEEK_SET ); - WriteInt32( fFile, FOURCC( "RIFF" ) ); - WriteInt32( fFile, fRiffBytesCount ); - WriteInt32( fFile, FOURCC( "AVI " ) ); - WriteInt32( fFile, FOURCC( "LIST" ) ); - WriteInt32( fFile, fHdrlBytesCount ); - WriteInt32( fFile, FOURCC( "hdrl" ) ); - - WriteMainHeader( fFile, &fMainHeader ); - - int strlSize; - strlSize = 4 + AVI_STREAM_HEADER_SIZE + BITMAP_INFO_SIZE; - WriteInt32( fFile, FOURCC( "LIST" ) ); - WriteInt32( fFile, strlSize ); - WriteInt32( fFile, FOURCC( "strl" ) ); - - WriteStreamHeader( fFile, &fVideoStreamHeader ); - WriteBitmapInfo( fFile, &fVideoStreamFormat ); - - if( fAudio1 ) - { - strlSize = 4 + AVI_STREAM_HEADER_SIZE + WAVE_FORMAT_EX_SIZE; - WriteInt32( fFile, FOURCC( "LIST" ) ); - WriteInt32( fFile, strlSize ); - WriteInt32( fFile, FOURCC( "strl" ) ); - WriteStreamHeader( fFile, &fAudio1StreamHeader ); - WriteWaveFormatEx( fFile, &fAudio1StreamFormat ); - } - - if( fAudio2 ) - { - strlSize = 4 + AVI_STREAM_HEADER_SIZE + WAVE_FORMAT_EX_SIZE; - WriteInt32( fFile, FOURCC( "LIST" ) ); - WriteInt32( fFile, strlSize ); - WriteInt32( fFile, FOURCC( "strl" ) ); - WriteStreamHeader( fFile, &fAudio2StreamHeader ); - WriteWaveFormatEx( fFile, &fAudio2StreamFormat ); - } - - /* a JUNK chunk to fill the free space. - size = 2048 -/ - 12 ("RIFFxxxxAVI ") - - 8 (hdrl's "LIS1Txxxx") - - fHdrlBytesCount - - 8 ("JUNKxxxx") - - 12 ("LISTxxxxmovi) */ - int junkSize = 2008 - fHdrlBytesCount; - WriteInt32( fFile, FOURCC( "JUNK" ) ); - WriteInt32( fFile, junkSize ); - for( uint32_t i = 0; i < 2008 - fHdrlBytesCount; i++ ) - { - WriteInt8( fFile, 0 ); - } - - /* movi list */ - WriteInt32( fFile, FOURCC( "LIST" ) ); - WriteInt32( fFile, fMoviBytesCount ); - WriteInt32( fFile, FOURCC( "movi" ) ); -} diff --git a/core/AviMuxer.h b/core/AviMuxer.h deleted file mode 100644 index 842f7a87a..000000000 --- a/core/AviMuxer.h +++ /dev/null @@ -1,153 +0,0 @@ -/* $Id: AviMuxer.h,v 1.10 2003/09/30 14:38:15 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_AVI_MUXER_H -#define HB_AVI_MUXER_H - -#include "Common.h" -#include "Fifo.h" -#include "Thread.h" - -/* Misc structures used in AVI headers */ -#define BITMAP_INFO_SIZE 52 -typedef struct BitmapInfo -{ - uint32_t FourCC; - uint32_t BytesCount; - uint32_t Size; - uint32_t Width; - uint32_t Height; - uint16_t Planes; - uint16_t BitCount; - uint32_t Compression; - uint32_t SizeImage; - uint32_t XPelsPerMeter; - uint32_t YPelsPerMeter; - uint32_t ClrUsed; - uint32_t ClrImportant; - uint8_t Blue; - uint8_t Green; - uint8_t Red; - uint8_t Reserved; -} BitmapInfo; - -#define WAVE_FORMAT_EX_SIZE 38 -typedef struct WaveFormatEx -{ - uint32_t FourCC; - uint32_t BytesCount; - uint16_t FormatTag; - uint16_t Channels; - uint32_t SamplesPerSec; - uint32_t AvgBytesPerSec; - uint16_t BlockAlign; - uint16_t BitsPerSample; - uint16_t Size; - - /* mp3 specific */ - uint16_t Id; - uint32_t Flags; - uint16_t BlockSize; - uint16_t FramesPerBlock; - uint16_t CodecDelay; -} WaveFormatEx; - -#define AVI_STREAM_HEADER_SIZE 64 -typedef struct AviStreamHeader -{ - uint32_t FourCC; - uint32_t BytesCount; - uint32_t Type; - uint32_t Handler; - uint32_t Flags; - uint16_t Priority; - uint16_t Language; - uint32_t InitialFrames; - uint32_t Scale; - uint32_t Rate; - uint32_t Start; - uint32_t Length; - uint32_t SuggestedBufferSize; - uint32_t Quality; - uint32_t SampleSize; - int16_t Left; - int16_t Top; - int16_t Right; - int16_t Bottom; -} AviStreamHeader; - -#define AVI_MAIN_HEADER_SIZE 64 -typedef struct AviMainHeader -{ - uint32_t FourCC; - uint32_t BytesCount; - uint32_t MicroSecPerFrame; - uint32_t MaxBytesPerSec; - uint32_t PaddingGranularity; - uint32_t Flags; - uint32_t TotalFrames; - uint32_t InitialFrames; - uint32_t Streams; - uint32_t SuggestedBufferSize; - uint32_t Width; - uint32_t Height; - uint32_t Reserved[4]; -} AviMainHeader; - -class HBAviIndex : public HBBuffer -{ - public: - HBAviIndex( uint32_t size ); - void WriteInt32( uint32_t val ); -}; - -class HBAviMuxer : public HBThread -{ - public: - HBAviMuxer( HBManager * manager, - HBTitle * title, HBAudio * audio1, - HBAudio * audio2, - char * fileName ); - - private: - void DoWork(); - bool AddVideoChunk(); - bool AddAudioChunk( int track ); - void UpdateMainHeader(); - - HBManager * fManager; - HBTitle * fTitle; - HBAudio * fAudio1; - HBAudio * fAudio2; - char * fFileName; - - FILE * fFile; - HBBuffer * fVideoBuffer; - HBBuffer * fAudio1Buffer; - HBBuffer * fAudio2Buffer; - - /* The main header */ - AviMainHeader fMainHeader; - - /* The video track */ - AviStreamHeader fVideoStreamHeader; - BitmapInfo fVideoStreamFormat; - - /* The audio tracks */ - AviStreamHeader fAudio1StreamHeader; - WaveFormatEx fAudio1StreamFormat; - AviStreamHeader fAudio2StreamHeader; - WaveFormatEx fAudio2StreamFormat; - - uint32_t fRiffBytesCount; - uint32_t fHdrlBytesCount; - uint32_t fMoviBytesCount; - - HBAviIndex * fIndex; - -}; - -#endif diff --git a/core/Common.cpp b/core/Common.cpp deleted file mode 100644 index 4087a001d..000000000 --- a/core/Common.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#if defined( SYS_BEOS ) -# include <OS.h> -#endif - -#include "Common.h" -#include "Fifo.h" -#include "MpegDemux.h" -#include "Languages.h" - -#include <stdarg.h> -#include <time.h> -#include <sys/time.h> -#include <dvdread/ifo_types.h> -#include <dvdplay/dvdplay.h> -#include <dvdplay/info.h> -#include <dvdplay/state.h> -#include <dvdplay/nav.h> - -extern "C" { -#include <mpeg2dec/mpeg2.h> -} - -void Snooze( uint64_t time ) -{ -#if defined( SYS_BEOS ) - snooze( time ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - usleep( time ); -#endif -} - -void Log( char * log, ... ) -{ - if( !getenv( "HB_DEBUG" ) ) - { - return; - } - - char string[1024]; - - /* Show the time */ - time_t _now = time( NULL ); - struct tm * now = localtime( &_now ); - sprintf( string, "[%02d:%02d:%02d] ", - now->tm_hour, now->tm_min, now->tm_sec ); - - /* Convert the message to a string */ - va_list args; - va_start( args, log ); - int ret = vsnprintf( string + 11, 1011, log, args ); - va_end( args ); - - /* Add the end of line */ - string[ret+11] = '\n'; - string[ret+12] = '\0'; - - /* Print it */ - fprintf( stderr, "%s", string ); -} - -char * LanguageForCode( int code ) -{ - char codeString[2]; - codeString[0] = ( code >> 8 ) & 0xFF; - codeString[1] = code & 0xFF; - - iso639_lang_t * lang; - for( lang = languages; lang->engName; lang++ ) - { - if( !strncmp( lang->iso639_1, codeString, 2 ) ) - { - if( *lang->nativeName ) - return lang->nativeName; - - return lang->engName; - } - } - - return "Unknown"; -} - -uint64_t GetDate() -{ - struct timeval tv; - gettimeofday( &tv, NULL ); - return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec ); -} - -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() -{ - fItems = (void**) malloc( HBLIST_DEFAULT_SIZE * sizeof( void* ) ); - fAllocItems = HBLIST_DEFAULT_SIZE; - fNbItems = 0; -} - -HBList::~HBList() -{ - free( fItems ); -} - -uint32_t HBList::CountItems() -{ - return fNbItems; -} - -void HBList::AddItem( void * item ) -{ - if( !item ) - { - return; - } - - if( fNbItems == fAllocItems ) - { - fAllocItems += HBLIST_DEFAULT_SIZE; - fItems = (void**) realloc( fItems, fAllocItems * sizeof( void* ) ); - } - - fItems[fNbItems] = item; - - fNbItems++; -} - -void HBList::RemoveItem( void * item ) -{ - if( !item || !fNbItems ) - { - return; - } - - uint32_t i; - for( i = 0; i < fNbItems; i++ ) - { - if( fItems[i] == item ) - { - break; - } - } - - if( fItems[i] != item ) - { - Log( "HBList::RemoveItem() : item not in the list" ); - return; - } - - for( ; i < fNbItems - 1; i++ ) - { - fItems[i] = fItems[i+1]; - } - - fNbItems--; -} - -void * HBList::ItemAt( uint32_t index ) -{ - if( index < fNbItems ) - { - return fItems[index]; - } - - return NULL; -} - -HBTitle::HBTitle( char * device, int index ) -{ - fDevice = strdup( device ); - fIndex = index; - - fAudioList = new HBList(); - fPSFifo = NULL; - fMpeg2Fifo = NULL; - fRawFifo = NULL; - fMpeg4Fifo = NULL; - - fTopCrop = 0; - fBottomCrop = 0; - fLeftCrop = 0; - fRightCrop = 0; - fBitrate = 1024; - fDeinterlace = false; - fTwoPass = false; -} - -HBTitle::~HBTitle() -{ - HBAudio * audio; - - while( ( audio = (HBAudio*) fAudioList->ItemAt( 0 ) ) ) - { - fAudioList->RemoveItem( audio ); - delete audio; - } - delete fAudioList; -} - -/* Audio track */ -HBAudio::HBAudio( int id, char * description ) -{ - fId = id; - fDescription = strdup( description ); - fOutSampleRate = 44100; - fOutBitrate = 128; - - fAc3Fifo = NULL; - fRawFifo = NULL; - fMp3Fifo = NULL; -} - -HBAudio::~HBAudio() -{ - free( fDescription ); -} diff --git a/core/Common.h b/core/Common.h deleted file mode 100644 index 3c138e2a1..000000000 --- a/core/Common.h +++ /dev/null @@ -1,215 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_COMMON_H -#define HB_COMMON_H - -/* Standard headers */ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <inttypes.h> -typedef uint8_t byte_t; - -/* Misc structures */ -typedef struct 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; -typedef struct AVFrame AVFrame; -typedef struct AVCodecContext AVCodecContext; -typedef struct ImgReSampleContext ImgReSampleContext; - -/* Classes */ -class HBAc3Decoder; -class HBAudio; -class HBAviIndex; -class HBAviMuxer; -class HBBuffer; -class HBDVDReader; -class HBFifo; -class HBList; -class HBLock; -class HBManager; -class HBMp3Encoder; -class HBMpeg2Decoder; -class HBMpeg4Encoder; -class HBMpegDemux; -class HBResizer; -class HBScanner; -class HBStatus; -class HBThread; -class HBTitle; -class HBWorker; - -/* Handy macros */ -#ifndef MIN -# define MIN( a, b ) ( ( (a) > (b) ) ? (b) : (a) ) -#endif -#ifndef MAX -# define MAX( a, b ) ( ( (a) > (b) ) ? (a) : (b) ) -#endif -#define EVEN( a ) ( ( (a) & 0x1 ) ? ( (a) + 1 ) : (a) ) -#define MULTIPLE_16( a ) ( 16 * ( ( (a) + 8 ) / 16 ) ) - -#define VOUT_ASPECT_FACTOR 432000 - -/* Global prototypes */ -void Snooze( uint64_t time ); -void Log( char * log, ... ); -char * LanguageForCode( int code ); -uint64_t GetDate(); -int GetCPUCount(); - -/* Possible states */ -typedef enum -{ - 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: - HBMode fMode; - - /* HB_MODE_SCANNING */ - char * fScannedVolume; - int fScannedTitle; - - /* HB_MODE_SCANDONE */ - HBList * fTitleList; - - /* HB_MODE_ENCODING || HB_MODE_SUSPENDED */ - float fPosition; - float fFrameRate; - uint32_t fFrames; - uint64_t fStartDate; - uint32_t fRemainingTime; /* in seconds */ - uint64_t fSuspendDate; - - /* HB_MODE_ERROR */ - HBError fError; -}; - -class HBList -{ - public: - HBList(); - ~HBList(); - uint32_t CountItems(); - void AddItem( void * item ); - void RemoveItem( void * item ); - void * ItemAt( uint32_t index ); - - private: - void ** fItems; - uint32_t fAllocItems; - uint32_t fNbItems; -}; - -class HBAudio -{ - public: - HBAudio( int id, char * description ); - ~HBAudio(); - - /* Ident */ - uint32_t fId; - char * fDescription; - - /* Settings */ - int fInSampleRate; - int fOutSampleRate; - int fInBitrate; - int fOutBitrate; - - int64_t fDelay; /* in ms */ - - /* Fifos */ - HBFifo * fAc3Fifo; - HBFifo * fRawFifo; - HBFifo * fMp3Fifo; - - /* Threads */ - HBAc3Decoder * fAc3Decoder; - HBMp3Encoder * fMp3Encoder; -}; - -class HBTitle -{ - public: - HBTitle( char * device, int index ); - ~HBTitle(); - - char * fDevice; - int fIndex; - uint64_t fLength; - - /* Video input */ - uint32_t fInWidth; - uint32_t fInHeight; - uint32_t fAspect; - uint32_t fRate; - uint32_t fScale; - - /* Video output */ - bool fDeinterlace; - uint32_t fOutWidth; - uint32_t fOutHeight; - uint32_t fOutWidthMax; - uint32_t fOutHeightMax; - uint32_t fTopCrop; - uint32_t fBottomCrop; - uint32_t fLeftCrop; - uint32_t fRightCrop; - uint32_t fBitrate; - bool fTwoPass; - - /* Audio infos */ - HBList * fAudioList; - - /* Fifos */ - HBFifo * fPSFifo; - HBFifo * fMpeg2Fifo; - HBFifo * fRawFifo; - HBFifo * fResizedFifo; - HBFifo * fMpeg4Fifo; - - /* Threads */ - HBDVDReader * fDVDReader; - HBMpegDemux * fMpegDemux; - HBMpeg2Decoder * fMpeg2Decoder; - HBResizer * fResizer; - HBMpeg4Encoder * fMpeg4Encoder; - HBAviMuxer * fAviMuxer; - HBWorker * fWorkers[4]; -}; - -#endif diff --git a/core/DVDRead.c b/core/DVDRead.c new file mode 100644 index 000000000..58e8f1031 --- /dev/null +++ b/core/DVDRead.c @@ -0,0 +1,328 @@ +/* $Id: DVDRead.c,v 1.4 2003/11/06 13:03:19 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "DVDRead.h" +#include "Fifo.h" +#include "Thread.h" + +#include <dvdread/ifo_types.h> +#include <dvdplay/dvdplay.h> +#include <dvdplay/info.h> +#include <dvdplay/state.h> +#include <dvdplay/nav.h> + +/* Local prototypes */ +static void DVDReadThread( void * ); +static int DoPass( HBDVDRead * ); +static int Demux( HBDVDRead * ); +static int Push( HBDVDRead *, HBFifo * fifo, HBBuffer ** buffer ); + +struct HBDVDRead +{ + HBHandle * handle; + + dvdplay_ptr vmg; + HBTitle * title; + HBAudio * audio; + HBAudio * optAudio; + int beginPosition; + int endPosition; + int pass; + HBBuffer * psBuffer; + HBList * esBufferList; + HBBuffer * videoBuf; + HBBuffer * audioBuf; + HBBuffer * optAudioBuf; + int videoStart; + int audioStart; + int optAudioStart; + + int die; + HBThread * thread; +}; + +HBDVDRead * HBDVDReadInit( HBHandle * handle, HBTitle * t, + HBAudio * a1, HBAudio * a2 ) +{ + HBDVDRead * d; + if( !( d = malloc( sizeof( HBDVDRead ) ) ) ) + { + HBLog( "HBDVDReadInit: malloc() failed, gonna crash" ); + return NULL; + } + + /* Initializations */ + d->handle = handle; + d->vmg = NULL; + d->title = t; + d->audio = a1; + d->optAudio = a2; + d->beginPosition = 0; + d->endPosition = 0; + d->pass = 0; + d->psBuffer = NULL; + d->esBufferList = HBListInit(); + d->videoBuf = NULL; + d->audioBuf = NULL; + d->optAudioBuf = NULL; + d->videoStart = -1; + d->audioStart = -1; + d->optAudioStart = -1; + + /* Launch the thread */ + d->die = 0; + d->thread = HBThreadInit( "dvd reader", DVDReadThread, d, + HB_NORMAL_PRIORITY ); + + return d; +} + +void HBDVDReadClose( HBDVDRead ** _d ) +{ + HBBuffer * buffer; + + HBDVDRead * d = *_d; + + /* Stop the thread */ + d->die = 1; + HBThreadClose( &d->thread ); + + /* Clean up */ + while( ( buffer = (HBBuffer*) HBListItemAt( d->esBufferList, 0 ) ) ) + { + HBListRemove( d->esBufferList, buffer ); + HBBufferClose( &buffer ); + } + HBListClose( &d->esBufferList ) ; + free( d ); + + (*_d) = NULL; +} + +static void DVDReadThread( void * _d ) +{ + HBDVDRead * d = (HBDVDRead*) _d; + uint8_t dummy[DVD_VIDEO_LB_LEN]; + int i; + + /* Open the device */ + d->vmg = dvdplay_open( d->title->device, NULL, NULL ); + if( !d->vmg ) + { + HBLog( "HBDVDRead: dvdplay_open() failed" ); + HBErrorOccured( d->handle, HB_ERROR_DVD_OPEN ); + return; + } + + /* Open the title */ + dvdplay_start( d->vmg, d->title->index ); + d->beginPosition = dvdplay_title_first( d->vmg ); + d->endPosition = dvdplay_title_end( d->vmg ); + + HBLog( "HBDVDRead: starting, blocks: %d to %d", + d->beginPosition, d->endPosition ); + + /* Lalala */ + dvdplay_read( d->vmg, dummy, 1 ); + + /* Do the job */ + for( i = 0; i < ( d->title->twoPass ? 2 : 1 ); i++ ) + { + dvdplay_seek( d->vmg, 0 ); + + HBLog( "HBDVDRead: starting pass %d of %d", i + 1, + d->title->twoPass ? 2 : 1 ); + + d->pass = d->title->twoPass ? ( i + 1 ) : 0; + + if( !DoPass( d ) ) + { + break; + } + } + + /* Flag the latest buffers so we know when we're done */ + if( !d->die ) + { + HBLog( "HBDVDRead: done" ); + + if( d->videoBuf ) + { + d->videoBuf->last = 1; + Push( d, d->title->mpeg2Fifo, &d->videoBuf ); + } + if( d->audioBuf ) + { + d->audioBuf->last = 1; + Push( d, d->audio->ac3Fifo, &d->audioBuf ); + } + if( d->optAudioBuf ) + { + d->optAudioBuf->last = 1; + Push( d, d->optAudio->ac3Fifo, &d->optAudioBuf ); + } + } + + /* Clean up */ + dvdplay_close( d->vmg ); +} + + +static int DoPass( HBDVDRead * d ) +{ + int i; + + for( i = 0; i < d->endPosition - d->beginPosition; i++ ) + { + d->psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN ); + d->psBuffer->position = + (float) i / ( d->endPosition - d->beginPosition ); + + if( d->pass ) + { + d->psBuffer->position /= 2; + + if( d->pass == 2 ) + { + d->psBuffer->position += 0.5; + } + } + d->psBuffer->pass = d->pass; + + if( dvdplay_read( d->vmg, d->psBuffer->data, 1 ) < 0 ) + { + HBLog( "HBDVDRead: dvdplay_read() failed" ); + HBErrorOccured( d->handle, HB_ERROR_DVD_READ ); + HBBufferClose( &d->psBuffer ); + return 0; + } + + if( !Demux( d ) ) + { + return 0; + } + } + + return 1; +} + +static int Demux( HBDVDRead * d ) +{ + HBBuffer * esBuffer; + + /* Demux */ + HBPStoES( &d->psBuffer, d->esBufferList ); + + /* Push buffers */ + while( ( esBuffer = (HBBuffer*) HBListItemAt( d->esBufferList, 0 ) ) ) + { + /* First pass: trash audio buffers */ + if( d->pass == 1 && esBuffer->streamId != 0xE0 ) + { + HBListRemove( d->esBufferList, esBuffer ); + HBBufferClose( &esBuffer ); + continue; + } + + if( esBuffer->streamId == 0xE0 ) + { + if( d->videoStart < 0 ) + { + d->videoStart = esBuffer->pts / 90; + HBLog( "HBDVDRead: got first 0xE0 packet (%d)", + d->videoStart ); + } + + if( d->videoBuf ) + { + d->videoBuf->last = 0; + if( !Push( d, d->title->mpeg2Fifo, &d->videoBuf ) ) + { + return 0; + } + } + + HBListRemove( d->esBufferList, esBuffer ); + d->videoBuf = esBuffer; + } + else if( esBuffer->streamId == d->audio->id ) + { + if( d->audioStart < 0 ) + { + d->audioStart = esBuffer->pts / 90; + HBLog( "HBDVDRead: got first 0x%x packet (%d)", + d->audio->id, d->audioStart ); + + d->audio->delay = d->audioStart - d->videoStart; + } + + if( d->audioBuf ) + { + d->audioBuf->last = 0; + if( !Push( d, d->audio->ac3Fifo, &d->audioBuf ) ) + { + return 0; + } + } + + HBListRemove( d->esBufferList, esBuffer ); + d->audioBuf = esBuffer; + } + else if( d->optAudio && esBuffer->streamId == d->optAudio->id ) + { + if( d->optAudioStart < 0 ) + { + d->optAudioStart = esBuffer->pts / 90; + HBLog( "HBDVDRead: got first 0x%x packet (%d)", + d->optAudio->id, d->optAudioStart ); + + d->optAudio->delay = d->optAudioStart - d->videoStart; + } + + if( d->optAudioBuf ) + { + d->optAudioBuf->last = 0; + if( !Push( d, d->optAudio->ac3Fifo, &d->optAudioBuf ) ) + { + return 0; + } + } + + HBListRemove( d->esBufferList, esBuffer ); + d->optAudioBuf = esBuffer; + } + else + { + HBListRemove( d->esBufferList, esBuffer ); + HBBufferClose( &esBuffer ); + } + } + + return 1; +} + +static int Push( HBDVDRead * d, HBFifo * fifo, HBBuffer ** buffer ) +{ + for( ;; ) + { + HBCheckPaused( d->handle ); + + if( HBFifoPush( fifo, buffer ) ) + { + return 1; + } + + if( d->die ) + { + break; + } + + HBSnooze( 10000 ); + } + + return 0; +} + diff --git a/core/DVDRead.h b/core/DVDRead.h new file mode 100644 index 000000000..7a9aa7e21 --- /dev/null +++ b/core/DVDRead.h @@ -0,0 +1,16 @@ +/* $Id: DVDRead.h,v 1.1 2003/11/03 12:08:00 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_DVD_READ_H +#define HB_DVD_READ_H + +#include "HandBrakeInternal.h" + +HBDVDRead * HBDVDReadInit( HBHandle *, HBTitle *, + HBAudio *, HBAudio * ); +void HBDVDReadClose( HBDVDRead ** ); + +#endif diff --git a/core/DVDReader.cpp b/core/DVDReader.cpp deleted file mode 100644 index c3c0e6f3e..000000000 --- a/core/DVDReader.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* $Id: DVDReader.cpp,v 1.18 2003/10/16 13:39:13 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#include "DVDReader.h" -#include "Manager.h" -#include "Fifo.h" - -#include <dvdread/ifo_types.h> -#include <dvdplay/dvdplay.h> -#include <dvdplay/info.h> -#include <dvdplay/state.h> -#include <dvdplay/nav.h> - -HBDVDReader::HBDVDReader( HBManager * manager, HBTitle * title ) - : HBThread( "dvdreader", HB_NORMAL_PRIORITY ) -{ - fManager = manager; - fTitle = title; - - Run(); -} - -void HBDVDReader::DoWork() -{ - /* Open the device */ - dvdplay_ptr vmg; - vmg = dvdplay_open( fTitle->fDevice, NULL, NULL ); - if( !vmg ) - { - Log( "HBDVDReader: dvdplay_open() failed" ); - fManager->Error( HB_ERROR_DVD_OPEN ); - return; - } - - bool die = false; - for( int i = 0; i < ( fTitle->fTwoPass ? 2 : 1 ); i++ ) - { - /* Open the title */ - dvdplay_start( vmg, fTitle->fIndex ); - - /* Read */ - HBBuffer * dvdBuffer; - int beginPosition = dvdplay_position( vmg ); - int endPosition = dvdplay_title_end( vmg ); - - while( dvdplay_position( vmg ) < endPosition ) - { - while( fSuspend ) - { - Snooze( 10000 ); - } - - dvdBuffer = new HBBuffer( DVD_VIDEO_LB_LEN ); - dvdBuffer->fPosition = (float) ( dvdplay_position( vmg ) - - beginPosition ) / - (float) ( endPosition - beginPosition ) ; - if( fTitle->fTwoPass ) - { - dvdBuffer->fPosition /= 2; - if( i == 1 ) - { - dvdBuffer->fPosition += 0.5; - } - } - dvdBuffer->fPass = fTitle->fTwoPass ? ( i + 1 ) : 0; - - if( dvdplay_read( vmg, dvdBuffer->fData, 1 ) < 0 ) - { - Log( "HBDVDReader: dvdplay_read() failed" ); - delete dvdBuffer; - fManager->Error( HB_ERROR_DVD_READ ); - die = true; - break; - } - - if( !Push( fTitle->fPSFifo, dvdBuffer ) ) - { - die = true; - break; - } - } - - if( die ) - { - break; - } - } - - if( !die ) - { - fManager->Done(); - } - - /* Clean up */ - dvdplay_close( vmg ); -} diff --git a/core/DVDReader.h b/core/DVDReader.h deleted file mode 100644 index b76f57566..000000000 --- a/core/DVDReader.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $Id: DVDReader.h,v 1.5 2003/09/30 14:38:15 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_DVD_READER_H -#define HB_DVD_READER_H - -#include "Common.h" -#include "Thread.h" - -class HBDVDReader : public HBThread -{ - public: - HBDVDReader( HBManager * manager, HBTitle * title ); - - private: - void DoWork(); - - HBManager * fManager; - HBTitle * fTitle; -}; - -#endif diff --git a/core/FfmpegEnc.c b/core/FfmpegEnc.c new file mode 100644 index 000000000..2118c29d6 --- /dev/null +++ b/core/FfmpegEnc.c @@ -0,0 +1,230 @@ +/* $Id: FfmpegEnc.c,v 1.5 2003/11/06 13:03:19 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "FfmpegEnc.h" +#include "Fifo.h" +#include "Work.h" + +#include <ffmpeg/avcodec.h> + +/* Extern functions */ +void HBSetPosition( HBHandle *, float ); + +/* Local prototypes */ +static int FfmpegEncWork( HBWork * ); + +struct HBFfmpegEnc +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBTitle * title; + + HBBuffer * mpeg4Buffer; + int pass; + AVCodecContext * context; + FILE * file; +}; + +HBFfmpegEnc * HBFfmpegEncInit( HBHandle * handle, HBTitle * title ) +{ + HBFfmpegEnc * f; + if( !( f = malloc( sizeof( HBFfmpegEnc ) ) ) ) + { + HBLog( "HBFfmpegEncInit: malloc() failed, gonna crash" ); + return NULL; + } + + f->name = strdup( "FfmpegEnc" ); + f->work = FfmpegEncWork; + + f->handle = handle; + f->title = title; + + f->mpeg4Buffer = NULL; + f->pass = 42; + f->context = NULL; + f->file = NULL; + + return f; +} + +void HBFfmpegEncClose( HBFfmpegEnc ** _f ) +{ + HBFfmpegEnc * f = *_f; + + if( f->context ) + { + HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", + f->pass ); + + avcodec_close( f->context ); + if( f->file ) + { + fclose( f->file ); + f->file = NULL; + } + } + free( f->name ); + free( f ); + + *_f = NULL; +} + +static int FfmpegEncWork( HBWork * w ) +{ + HBFfmpegEnc * f = (HBFfmpegEnc*) w; + HBTitle * title = f->title; + + HBBuffer * scaledBuffer; + HBBuffer * mpeg4Buffer; + AVFrame * frame; + + int didSomething = 0; + + if( f->mpeg4Buffer ) + { + if( HBFifoPush( title->mpeg4Fifo, &f->mpeg4Buffer ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + } + + if( ( scaledBuffer = HBFifoPop( title->scaledFifo ) ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + /* Init or re-init if needed */ + if( scaledBuffer->pass != f->pass ) + { + AVCodec * codec; + AVCodecContext * context; + + if( f->context ) + { + HBLog( "HBFfmpegEnc: closing libavcodec (pass %d)", + f->pass ); + + avcodec_close( f->context ); + if( f->file ) + { + fclose( f->file ); + f->file = NULL; + } + } + + f->pass = scaledBuffer->pass; + + HBLog( "HBFfmpegEnc: opening libavcodec (pass %d)", f->pass ); + codec = avcodec_find_encoder( CODEC_ID_MPEG4 ); + if( !codec ) + { + HBLog( "HBFfmpegEnc: avcodec_find_encoder() failed" ); + HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); + return didSomething; + } + + context = avcodec_alloc_context(); + context->bit_rate = 1024 * title->bitrate; + context->bit_rate_tolerance = 10240 * title->bitrate; + context->width = title->outWidth; + context->height = title->outHeight; + context->frame_rate = title->rate; + context->frame_rate_base = title->rateBase; + context->gop_size = 10 * title->rate / + title->rateBase; + + if( f->pass ) + { + char fileName[1024]; memset( fileName, 0, 1024 ); + sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", + HBGetPid( f->handle ) ); + + if( f->pass == 1 ) + { + f->file = fopen( fileName, "w" ); + + context->flags |= CODEC_FLAG_PASS1; + } + else + { + FILE * file; + int size; + char * log; + + file = fopen( fileName, "r" ); + fseek( file, 0, SEEK_END ); + size = ftell( file ); + fseek( file, 0, SEEK_SET ); + if( !( log = malloc( size + 1 ) ) ) + { + HBLog( "HBFfmpegEnc: malloc() failed, gonna crash" ); + } + log[size] = '\0'; + fread( log, size, 1, file ); + fclose( file ); + + context->flags |= CODEC_FLAG_PASS2; + context->stats_in = log; + } + } + + if( avcodec_open( context, codec ) < 0 ) + { + HBLog( "HBFfmpegEnc: avcodec_open() failed" ); + HBErrorOccured( f->handle, HB_ERROR_MPEG4_INIT ); + return didSomething; + } + + f->context = context; + } + + frame = avcodec_alloc_frame(); + frame->data[0] = scaledBuffer->data; + frame->data[1] = frame->data[0] + title->outWidth * + title->outHeight; + frame->data[2] = frame->data[1] + title->outWidth * + title->outHeight / 4; + frame->linesize[0] = title->outWidth; + frame->linesize[1] = title->outWidth / 2; + frame->linesize[2] = title->outWidth / 2; + + mpeg4Buffer = HBBufferInit( 3 * title->outWidth * + title->outHeight / 2 ); + mpeg4Buffer->position = scaledBuffer->position; + mpeg4Buffer->size = + avcodec_encode_video( f->context, mpeg4Buffer->data, + mpeg4Buffer->alloc, frame ); + mpeg4Buffer->keyFrame = f->context->coded_frame->key_frame; + + /* Inform the GUI about the current position */ + HBPosition( f->handle, scaledBuffer->position ); + + if( f->pass == 1 ) + { + if( f->context->stats_out ) + { + fprintf( f->file, "%s", f->context->stats_out ); + } + HBBufferClose( &mpeg4Buffer ); + } + + HBBufferClose( &scaledBuffer ); + free( frame ); + + f->mpeg4Buffer = mpeg4Buffer; + + return didSomething; +} diff --git a/core/FfmpegEnc.h b/core/FfmpegEnc.h new file mode 100644 index 000000000..8ab622011 --- /dev/null +++ b/core/FfmpegEnc.h @@ -0,0 +1,15 @@ +/* $Id: FfmpegEnc.h,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_FFMPEG_ENC_H +#define HB_FFMPEG_ENC_H + +#include "HandBrakeInternal.h" + +HBFfmpegEnc * HBFfmpegEncInit( HBHandle *, HBTitle * ); +void HBFfmpegEncClose( HBFfmpegEnc ** ); + +#endif diff --git a/core/Fifo.c b/core/Fifo.c new file mode 100644 index 000000000..a8f6034c0 --- /dev/null +++ b/core/Fifo.c @@ -0,0 +1,105 @@ +/* $Id: Fifo.c,v 1.2 2003/11/05 19:14:37 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Fifo.h" + +HBBuffer * HBBufferInit( int size ) +{ + HBBuffer * b; + if( !( b = malloc( sizeof( HBBuffer ) ) ) ) + { + HBLog( "HBBufferInit: malloc() failed, gonna crash" ); + return NULL; + } + + b->alloc = size; + b->size = size; + + if( !( b->data = malloc( size ) ) ) + { + HBLog( "HBBufferInit: malloc() failed, gonna crash" ); + free( b ); + return NULL; + } + + b->position = 0.0; + b->streamId = 0; + b->keyFrame = 0; + b->pts = 0; + b->pass = 0; + b->last = 0; + + return b; +} + +void HBBufferReAlloc( HBBuffer * b, int size ) +{ + b->alloc = size; + b->data = realloc( b->data, size ); + + if( !b->data ) + { + HBLog( "HBBufferReAlloc: realloc() failed, gonna crash soon" ); + } +} + +void HBBufferClose( HBBuffer ** b ) +{ + free( (*b)->data ); + (*b) = NULL; +} + +HBFifo * HBFifoInit( int capacity ) +{ + HBFifo * f; + if( !( f = malloc( sizeof( HBFifo ) ) ) ) + { + HBLog( "HBFifoInit: malloc() failed, gonna crash" ); + return NULL; + } + + f->capacity = capacity; + f->whereToPush = 0; + f->whereToPop = 0; + + if( !( f->buffers = malloc( ( capacity + 1 ) * sizeof( void* ) ) ) ) + { + HBLog( "HBFifoInit: malloc() failed, gonna crash" ); + free( f ); + return NULL; + } + + f->lock = HBLockInit(); + + return f; +} + +int HBFifoSize( HBFifo * f ) +{ + return ( f->capacity + 1 + f->whereToPush - f->whereToPop ) % + ( f->capacity + 1 ); +} + +void HBFifoClose( HBFifo ** _f ) +{ + HBFifo * f = (*_f); + + HBLog( "HBFifoClose: trashing %d buffer%s", + HBFifoSize( f ), ( HBFifoSize( f ) > 1 ) ? "s" : "" ); + + while( f->whereToPush != f->whereToPop ) + { + HBBufferClose( &(f->buffers[f->whereToPop]) ); + f->whereToPop++; + f->whereToPop %= ( f->capacity + 1 ); + } + + HBLockClose( &f->lock ); + free( f->buffers ); + free( f ); + (*_f) = NULL; +} + diff --git a/core/Fifo.cpp b/core/Fifo.cpp deleted file mode 100644 index d1d051c33..000000000 --- a/core/Fifo.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#include "Fifo.h" -#include "Thread.h" - -HBBuffer::HBBuffer( uint32_t size ) -{ - fAllocSize = size; - fSize = size; - fKeyFrame = false; - fData = (uint8_t*) malloc( size ); - fPosition = 0; - - if( !fData ) - { - Log( "HBBuffer::HBBuffer() : malloc() failed, gonna crash soon" ); - } -} - -HBBuffer::~HBBuffer() -{ - free( fData ); -} - -void HBBuffer::ReAlloc( uint32_t size ) -{ - fData = (uint8_t*) realloc( fData, size ); - - if( !fData ) - { - Log( "HBBuffer::ReAlloc() : realloc() failed, gonna crash soon" ); - } - - fAllocSize = size; -} - -/* Constructor */ -HBFifo::HBFifo( int capacity ) -{ - fCapacity = capacity; - - fWhereToPush = 0; - fWhereToPop = 0; - fBuffers = (HBBuffer**) malloc( ( fCapacity + 1 ) * sizeof( void* ) ); - fLock = new HBLock(); -} - -HBFifo::~HBFifo() -{ - Log( "HBFifo::~HBFifo: trashing %d buffer%s", - Size(), Size() ? "s" : "" ); - - /* Empty the fifo */ - while( fWhereToPush != fWhereToPop ) - { - HBBuffer * buffer = fBuffers[fWhereToPop]; - fWhereToPop++; - fWhereToPop %= ( fCapacity + 1 ); - delete buffer; - } - - /* Cleaning */ - free( fBuffers ); - - delete fLock; -} - -/* Size() : returns how much the fifo is currently filled */ -int HBFifo::Size() -{ - return ( fCapacity + 1 + fWhereToPush - fWhereToPop ) % - ( fCapacity + 1 ); -} - -/* Capacity() : simply returns the fifo capacity... */ -int HBFifo::Capacity() -{ - return fCapacity; -} - -/* Push() - returns immediatly (true if successful, false otherwise ) */ -bool HBFifo::Push( HBBuffer * buffer ) -{ - fLock->Lock(); - - if( Size() < fCapacity ) - { - fBuffers[fWhereToPush] = buffer; - fWhereToPush++; - fWhereToPush %= ( fCapacity + 1 ); - fLock->Unlock(); - return true; - } - - fLock->Unlock(); - return false; -} - -/* Pop() - returns immediatly (a pointer to a buffer if successful, - NULL otherwise ) */ -HBBuffer * HBFifo::Pop() -{ - fLock->Lock(); - - if( fWhereToPush != fWhereToPop ) - { - HBBuffer * buffer = fBuffers[fWhereToPop]; - fWhereToPop++; - fWhereToPop %= ( fCapacity + 1 ); - fLock->Unlock(); - return buffer; - } - - fLock->Unlock(); - return NULL; -} diff --git a/core/Fifo.h b/core/Fifo.h index 69200d30c..758125ebd 100644 --- a/core/Fifo.h +++ b/core/Fifo.h @@ -1,49 +1,81 @@ -/* $Id: Fifo.h,v 1.11 2003/09/30 14:38:15 titer Exp $ +/* $Id: Fifo.h,v 1.3 2003/11/06 13:07:52 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #ifndef HB_FIFO_H #define HB_FIFO_H -#include "Common.h" +#include "Utils.h" +#include "Thread.h" -class HBBuffer +struct HBBuffer { - public: - HBBuffer( uint32_t size ); - ~HBBuffer(); - void ReAlloc( uint32_t size ); - - uint32_t fAllocSize; - uint32_t fSize; - uint8_t * fData; - - float fPosition; - uint32_t fStreamId; - bool fKeyFrame; - uint64_t fPTS; - uint32_t fPass; + int alloc; + int size; + uint8_t * data; + + float position; + int streamId; + int keyFrame; + uint64_t pts; + int pass; + int last; }; -class HBFifo +HBBuffer * HBBufferInit( int size ); +void HBBufferReAlloc( HBBuffer *, int size ); +void HBBufferClose( HBBuffer ** ); + +struct HBFifo { - public: - HBFifo( int capacity = 32 ); - ~HBFifo(); - - int Size(); - int Capacity(); - bool Push( HBBuffer * buffer ); - HBBuffer * Pop(); - - private: - int fCapacity; - int fWhereToPush; - int fWhereToPop; - HBBuffer ** fBuffers; - HBLock * fLock; + int capacity; + int whereToPush; + int whereToPop; + HBBuffer ** buffers; + HBLock * lock; }; +HBFifo * HBFifoInit( int capacity ); +int HBFifoSize( HBFifo * ); +static inline int HBFifoPush( HBFifo *, HBBuffer ** ); +static inline HBBuffer * HBFifoPop( HBFifo * ); +void HBFifoClose( HBFifo ** ); + +static inline int HBFifoPush( HBFifo * f, HBBuffer ** b ) +{ + HBLockLock( f->lock ); + + if( HBFifoSize( f ) < f->capacity ) + { + f->buffers[f->whereToPush] = *b; + f->whereToPush++; + f->whereToPush %= ( f->capacity + 1 ); + HBLockUnlock( f->lock ); + *b = NULL; + return 1; + } + + HBLockUnlock( f->lock ); + return 0; +} + +static inline HBBuffer * HBFifoPop( HBFifo * f ) +{ + HBLockLock( f->lock ); + + if( f->whereToPush != f->whereToPop ) + { + HBBuffer * b = f->buffers[f->whereToPop]; + f->whereToPop++; + f->whereToPop %= ( f->capacity + 1 ); + HBLockUnlock( f->lock ); + return b; + } + + HBLockUnlock( f->lock ); + return NULL; +} + #endif diff --git a/core/HandBrake.c b/core/HandBrake.c new file mode 100644 index 000000000..3f84a5757 --- /dev/null +++ b/core/HandBrake.c @@ -0,0 +1,767 @@ +/* $Id: HandBrake.c,v 1.15 2003/11/07 21:52:57 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "HandBrakeInternal.h" + +#include <ffmpeg/avcodec.h> + +#include "Ac3Dec.h" +#include "AviMux.h" +#include "DVDRead.h" +#include "FfmpegEnc.h" +#include "Fifo.h" +#include "Mp3Enc.h" +#include "Mpeg2Dec.h" +#include "Scale.h" +#include "Scan.h" +#include "Thread.h" +#include "Work.h" +#include "XvidEnc.h" + +/* Local prototypes */ +static void HandBrakeThread( void * ); +static void _StopRip( HBHandle * ); +static void FixPictureSettings( HBTitle * ); +static int GetCPUCount(); + +struct HBHandle +{ + HBThread * thread; + int die; + int pid; + + int cpuCount; + + int stopScan; + int stopRip; + int ripDone; + int error; + + HBScan * scan; + + HBLock * lock; + HBStatus status; + int modeChanged; + HBTitle * curTitle; + HBAudio * curAudio; + HBAudio * curOptAudio; + + int frames; + uint64_t beginDate; + int framesSinceFpsUpdate; + uint64_t lastFpsUpdate; + uint64_t pauseDate; + + HBLock * pauseLock; +}; + +HBHandle * HBInit( int debug, int cpuCount ) +{ + HBHandle * h; + if( !( h = malloc( sizeof( HBHandle ) ) ) ) + { + HBLog( "HBInit: malloc() failed, gonna crash" ); + return NULL; + } + + /* See HBLog() in Utils.cpp */ + if( debug ) + { + putenv( "HB_DEBUG=1" ); + } + + /* Init libavcodec */ + avcodec_init(); + register_avcodec( &mpeg4_encoder ); + + /* Check CPU count */ + if( !cpuCount ) + { + h->cpuCount = GetCPUCount(); + HBLog( "HBInit: %d CPU%s detected", h->cpuCount, + ( h->cpuCount > 1 ) ? "s" : "" ); + } + else + { + if( cpuCount < 1 ) + { + HBLog( "HBInit: invalid CPU count (%d), using 1", + cpuCount ); + h->cpuCount = 1; + } + else if( cpuCount > 8 ) + { + HBLog( "HBInit: invalid CPU count (%d), using 8", + cpuCount ); + h->cpuCount = 8; + } + else + { + HBLog( "HBInit: user specified %d CPU%s", + cpuCount, ( cpuCount > 1 ) ? "s" : "" ); + h->cpuCount = cpuCount; + } + } + + /* Initializations */ + h->stopScan = 0; + h->stopRip = 0; + h->ripDone = 0; + h->error = 0; + + h->scan = NULL; + + h->lock = HBLockInit(); + h->modeChanged = 1; + h->status.mode = HB_MODE_NEED_DEVICE; + h->curTitle = NULL; + h->curAudio = NULL; + h->curOptAudio = NULL; + + h->pauseLock = HBLockInit(); + + h->die = 0; + h->thread = HBThreadInit( "libhb", HandBrakeThread, h, + HB_NORMAL_PRIORITY ); + + return h; +} + +int HBGetStatus( HBHandle * h, HBStatus * status ) +{ + HBLockLock( h->lock ); + memcpy( status, &h->status, sizeof( HBStatus ) ); + + if( !h->modeChanged ) + { + HBLockUnlock( h->lock ); + return 0; + } + + h->modeChanged = 0; + HBLockUnlock( h->lock ); + return 1; +} + +void HBScanDevice( HBHandle * h, char * device, int title ) +{ + if( !( h->status.mode & ( HB_MODE_NEED_DEVICE | + HB_MODE_INVALID_DEVICE ) ) ) + { + HBLog( "HBScanDevice: current mode is %d, aborting", + h->status.mode ); + return; + } + + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HB_MODE_SCANNING; + h->status.scannedTitle = 0; + HBLockUnlock( h->lock ); + + h->scan = HBScanInit( h, device, title ); +} + +void HBStartRip( HBHandle * h, HBTitle * t, + HBAudio * a1, HBAudio * a2 ) +{ + int i; + + if( !( h->status.mode & ( HB_MODE_READY_TO_RIP | HB_MODE_DONE | + HB_MODE_CANCELED | HB_MODE_ERROR ) ) ) + { + HBLog( "HBStartRip: current mode is %d, aborting", + h->status.mode ); + return; + } + + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HB_MODE_ENCODING; + h->status.position = 0.0; + h->status.pass = 1; + h->status.passCount = t->twoPass ? 2 : 1; + h->frames = 0; + h->framesSinceFpsUpdate = 0; + HBLockUnlock( h->lock ); + + FixPictureSettings( t ); + + /* Create fifos */ + t->mpeg2Fifo = HBFifoInit( 512 ); + t->rawFifo = HBFifoInit( 1 ); + t->scaledFifo = HBFifoInit( 1 ); + t->mpeg4Fifo = HBFifoInit( 1 ); + a1->ac3Fifo = HBFifoInit( 512 ); + a1->rawFifo = HBFifoInit( 1 ); + a1->mp3Fifo = HBFifoInit( 1 ); + if( a2 ) + { + a2->ac3Fifo = HBFifoInit( 512 ); + a2->rawFifo = HBFifoInit( 1 ); + a2->mp3Fifo = HBFifoInit( 1 ); + } + + /* Create work objects */ + t->mpeg2Dec = HBMpeg2DecInit( h, t ); + t->scale = HBScaleInit( h, t ); + + if( t->codec == HB_CODEC_FFMPEG ) + t->ffmpegEnc = HBFfmpegEncInit( h, t ); + else if( t->codec == HB_CODEC_XVID ) + t->xvidEnc = HBXvidEncInit( h, t ); + + a1->ac3Dec = HBAc3DecInit( h, a1 ); + a1->mp3Enc = HBMp3EncInit( h, a1 ); + if( a2 ) + { + a2->ac3Dec = HBAc3DecInit( h, a2 ); + a2->mp3Enc = HBMp3EncInit( h, a2 ); + } + + /* Create threads */ + t->dvdRead = HBDVDReadInit( h, t, a1, a2 ); + t->aviMux = HBAviMuxInit( h, t, a1, a2 ); + for( i = 0; i < h->cpuCount; i++ ) + { + t->workThreads[i] = HBWorkThreadInit( h, t, a1, a2, i ? 0 : 1 ); + } + + h->curTitle = t; + h->curAudio = a1; + h->curOptAudio = a2; +} + +void HBPauseRip( HBHandle * h ) +{ + if( h->status.mode != HB_MODE_ENCODING ) + { + HBLog( "HBPauseRip: current mode is %d, aborting", + h->status.mode ); + return; + } + + h->pauseDate = HBGetDate(); + HBLockLock( h->pauseLock ); + HBLockLock( h->lock ); + h->status.mode = HB_MODE_PAUSED; + h->modeChanged = 1; + HBLockUnlock( h->lock ); +} + +void HBResumeRip( HBHandle * h ) +{ + if( h->status.mode != HB_MODE_PAUSED ) + { + HBLog( "HBResumeRip: current mode is %d, aborting", + h->status.mode ); + return; + } + + h->beginDate += HBGetDate() - h->pauseDate; + h->lastFpsUpdate += HBGetDate() - h->pauseDate; + HBLockUnlock( h->pauseLock ); + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HB_MODE_ENCODING; + HBLockUnlock( h->lock ); +} + +void HBStopRip( HBHandle * h ) +{ + if( !( h->status.mode & ( HB_MODE_ENCODING | HB_MODE_PAUSED ) ) ) + { + HBLog( "HBStopRip: current mode is %d, aborting", + h->status.mode ); + return; + } + + if( h->status.mode & HB_MODE_PAUSED ) + { + HBLockUnlock( h->pauseLock ); + } + + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HB_MODE_STOPPING; + HBLockUnlock( h->lock ); + h->stopRip = 1; +} + +uint8_t * HBGetPreview( HBHandle * h, HBTitle * t, int picture ) +{ + AVPicture pic1, pic2, pic3, pic4; + uint8_t * buf1, * buf2, * buf3, * buf4; + char fileName[1024]; + FILE * file; + ImgReSampleContext * resampleContext; + int8_t * preview, * pen; + int i; + + FixPictureSettings( t ); + + buf1 = malloc( 3 * t->inWidth * t->inHeight / 2 ); + buf2 = malloc( 3 * t->inWidth * t->inHeight / 2 ); + buf3 = malloc( 3 * t->outWidth * t->outHeight / 2 ); + buf4 = malloc( 4 * t->outWidth * t->outHeight ); + + if( !buf1 || !buf2 || !buf3 || !buf4 ) + { + HBLog( "HBGetPreview: malloc() failed, gonna crash" ); + return NULL; + } + + /* Original YUV picture */ + avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, t->inWidth, + t->inHeight ); + + /* Deinterlaced YUV picture */ + avpicture_fill( &pic2, buf2, PIX_FMT_YUV420P, + t->inWidth, t->inHeight ); + + /* Scaled YUV picture */ + avpicture_fill( &pic3, buf3, PIX_FMT_YUV420P, t->outWidth, + t->outHeight ); + + /* Scaled RGB picture ) */ + avpicture_fill( &pic4, buf4, PIX_FMT_RGBA32, t->outWidth, + t->outHeight ); + + /* Get the original image from the temp file */ + memset( fileName, 0, 1024 ); + sprintf( fileName, "/tmp/HB.%d.%d.%d", h->pid, t->index, + picture ); + file = fopen( fileName, "r" ); + if( file ) + { + fread( buf1, 3 * t->inWidth * t->inHeight / 2, 1, file ); + fclose( file ); + } + else + { + HBLog( "HBGetPreview: could not open %s", fileName ); + memset( buf1, 0, 3 * t->inWidth * t->inHeight / 2 ); + } + + /* Deinterlace if needed, and scale */ + resampleContext = + img_resample_full_init( t->outWidth, t->outHeight, + t->inWidth, t->inHeight, + t->topCrop, t->bottomCrop, + t->leftCrop, t->rightCrop ); + if( t->deinterlace ) + { + avpicture_deinterlace( &pic2, &pic1, PIX_FMT_YUV420P, + t->inWidth, t->inHeight ); + img_resample( resampleContext, &pic3, &pic2 ); + } + else + { + img_resample( resampleContext, &pic3, &pic1 ); + } + + /* Convert to RGB */ + img_convert( &pic4, PIX_FMT_RGBA32, &pic3, PIX_FMT_YUV420P, + t->outWidth, t->outHeight ); + + /* Create the final preview */ + preview = malloc( 4 * ( t->outWidthMax + 2 ) * + ( t->outHeightMax + 2 ) ); + + if( !preview ) + { + HBLog( "HBGetPreview: malloc() failed, gonna crash" ); + return NULL; + } + + /* Blank it */ + memset( preview, 0x80, + 4 * ( t->outWidthMax + 2 ) * ( t->outHeightMax + 2 ) ); + + /* Draw the picture (centered) and draw the cropping zone */ + pen = preview + ( t->outHeightMax - t->outHeight ) * + ( t->outWidthMax + 2 ) * 2 + + ( t->outWidthMax - t->outWidth ) * 2; + + memset( pen, 0xFF, 4 * ( t->outWidth + 2 ) ); + pen += 4 * ( t->outWidthMax + 2 ); + + for( i = 0; i < t->outHeight; i++ ) + { + uint8_t * nextLine = pen + 4 * ( t->outWidthMax + 2 ); + + memset( pen, 0xFF, 4 ); + pen += 4; + memcpy( pen, buf4 + 4 * t->outWidth * i, 4 * t->outWidth ); + pen += 4 * t->outWidth; + memset( pen, 0xFF, 4 ); + + pen = nextLine; + } + + memset( pen, 0xFF, 4 * ( t->outWidth + 2 ) ); + + /* Free memory */ + free( buf1 ); + free( buf2 ); + free( buf3 ); + free( buf4 ); + + return preview; + return NULL; +} + +void HBClose( HBHandle ** _h ) +{ + char command[1024]; + + HBHandle * h = *_h; + + h->die = 1; + HBThreadClose( &h->thread ); + + if( h->status.mode == HB_MODE_SCANNING ) + { + HBScanClose( &h->scan ); + } + else if( h->status.mode == HB_MODE_PAUSED ) + { + HBLockUnlock( h->pauseLock ); + _StopRip( h ); + } + else if( h->status.mode == HB_MODE_ENCODING ) + { + _StopRip( h ); + } + + memset( command, 0, 1024 ); + sprintf( command, "rm -f /tmp/HB.%d.*", h->pid ); + system( command ); + + if( h->status.titleList ) + { + HBTitle * title; + while( ( title = HBListItemAt( h->status.titleList, 0 ) ) ) + { + HBListRemove( h->status.titleList, title ); + HBTitleClose( &title ); + } + HBListClose( &h->status.titleList ); + } + + HBLockClose( &h->lock ); + HBLockClose( &h->pauseLock ); + free( h ); + + *_h = NULL; +} + +/* Following functions are called by libhb's internal threads */ +void HBCheckPaused( HBHandle * h ) +{ + HBLockLock( h->pauseLock ); + HBLockUnlock( h->pauseLock ); +} + +void HBScanning( HBHandle * h, int title ) +{ + HBLockLock( h->lock ); + h->status.scannedTitle = title; + HBLockUnlock( h->lock ); +} + +void HBScanDone( HBHandle * h, HBList * titleList ) +{ + h->status.titleList = titleList; + h->stopScan = 1; +} + +int HBGetPid( HBHandle * h ) +{ + return h->pid; +} + +void HBDone( HBHandle * h ) +{ + h->ripDone = 1; +} + +void HBPosition( HBHandle * h, float position ) +{ + if( !h->frames ) + { + h->beginDate = HBGetDate(); + h->lastFpsUpdate = h->beginDate; + } + + h->frames++; + h->framesSinceFpsUpdate++; + + HBLockLock( h->lock ); + if( position - h->status.position > 0.0001 || h->frames == 2 ) + { + HBLog( "Progress: %.2f %%", 100.0 * position ); + h->status.position = position; + + if( h->curTitle->twoPass ) + h->status.pass = ( position < 0.5 ) ? 1 : 2; + else + h->status.pass = 1; + } + if( HBGetDate() - h->lastFpsUpdate > 1000000 ) + { + h->status.frameRate = 1000000.0 * h->framesSinceFpsUpdate / + ( HBGetDate() - h->lastFpsUpdate ); + h->status.avFrameRate = 1000000.0 * h->frames / + ( HBGetDate() - h->beginDate ); + h->status.remainingTime = ( 1.0 - h->status.position ) * + ( HBGetDate() - h->beginDate ) / + h->status.position / 1000000; + + HBLog( "Speed: %.2f fps (average: %.2f fps, " + "remaining: %02d:%02d:%02d)", + h->status.frameRate, h->status.avFrameRate, + h->status.remainingTime / 3600, + ( h->status.remainingTime / 60 ) % 60, + h->status.remainingTime % 60 ); + + h->lastFpsUpdate = HBGetDate(); + h->framesSinceFpsUpdate = 0; + } + HBLockUnlock( h->lock ); +} + +void HBErrorOccured( HBHandle * h, HBError error ) +{ + if( !( h->status.mode & ( HB_MODE_ENCODING | HB_MODE_PAUSED ) ) ) + { + return; + } + + h->status.error = error; + h->error = 1; +} + +/* Local functions */ +static void HandBrakeThread( void * _h ) +{ + HBHandle * h = (HBHandle*) _h; + + h->pid = getpid(); + + while( !h->die ) + { + if( h->stopScan ) + { + HBScanClose( &h->scan ); + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HBListCountItems( h->status.titleList ) ? + HB_MODE_READY_TO_RIP : HB_MODE_INVALID_DEVICE; + HBLockUnlock( h->lock ); + h->stopScan = 0; + } + + if( h->stopRip ) + { + _StopRip( h ); + + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HB_MODE_CANCELED; + HBLockUnlock( h->lock ); + + h->stopRip = 0; + } + + if( h->ripDone ) + { + /* Wait a bit */ + HBSnooze( 500000 ); + + _StopRip( h ); + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HB_MODE_DONE; + HBLockUnlock( h->lock ); + + h->ripDone = 0; + } + + if( h->error ) + { + _StopRip( h ); + + HBLockLock( h->lock ); + h->modeChanged = 1; + h->status.mode = HB_MODE_ERROR; + HBLockUnlock( h->lock ); + + h->error = 0; + } + + HBSnooze( 10000 ); + } +} + +static void _StopRip( HBHandle * h ) +{ + int i; + + /* Stop threads */ + HBDVDReadClose( &h->curTitle->dvdRead ); + HBAviMuxClose( &h->curTitle->aviMux ); + for( i = 0; i < h->cpuCount; i++ ) + { + HBWorkThreadClose( &h->curTitle->workThreads[h->cpuCount-i-1] ); + } + + /* Clean up */ + HBMpeg2DecClose( &h->curTitle->mpeg2Dec ); + HBScaleClose( &h->curTitle->scale ); + + if( h->curTitle->codec == HB_CODEC_FFMPEG ) + HBFfmpegEncClose( &h->curTitle->ffmpegEnc ); + else if( h->curTitle->codec == HB_CODEC_XVID ) + HBXvidEncClose( &h->curTitle->xvidEnc ); + + HBAc3DecClose( &h->curAudio->ac3Dec ); + HBMp3EncClose( &h->curAudio->mp3Enc ); + if( h->curOptAudio ) + { + HBAc3DecClose( &h->curOptAudio->ac3Dec ); + HBMp3EncClose( &h->curOptAudio->mp3Enc ); + } + + /* Destroy fifos */ + HBFifoClose( &h->curTitle->mpeg2Fifo ); + HBFifoClose( &h->curTitle->rawFifo ); + HBFifoClose( &h->curTitle->scaledFifo ); + HBFifoClose( &h->curTitle->mpeg4Fifo ); + HBFifoClose( &h->curAudio->ac3Fifo ); + HBFifoClose( &h->curAudio->rawFifo ); + HBFifoClose( &h->curAudio->mp3Fifo ); + if( h->curOptAudio ) + { + HBFifoClose( &h->curOptAudio->ac3Fifo ); + HBFifoClose( &h->curOptAudio->rawFifo ); + HBFifoClose( &h->curOptAudio->mp3Fifo ); + } +} + +static void FixPictureSettings( HBTitle * t ) +{ + /* Sanity checks */ + t->topCrop = EVEN( t->topCrop ); + t->bottomCrop = EVEN( t->bottomCrop ); + t->leftCrop = EVEN( t->leftCrop ); + t->rightCrop = EVEN( t->rightCrop ); + + t->outWidth = MIN( t->outWidth, t->outWidthMax ); + t->outWidth = MAX( 16, t->outWidth ); + + t->outHeight = + MULTIPLE_16( (uint64_t) t->outWidth * t->inWidth * + ( t->inHeight - t->topCrop - t->bottomCrop ) * + VOUT_ASPECT_FACTOR / + ( (uint64_t) t->inHeight * + ( t->inWidth - t->leftCrop - t->rightCrop ) * + t->aspect ) ); + t->outHeight = MAX( 16, t->outHeight ); + + if( t->outHeight > t->outHeightMax ) + { + t->outHeight = t->outHeightMax; + t->outWidth = + MULTIPLE_16( (uint64_t) t->outHeight * t->inHeight * + ( t->inWidth - t->leftCrop - t->rightCrop ) * + t->aspect / + ( (uint64_t) t->inWidth * + ( t->inHeight - t->topCrop - t->bottomCrop ) * + VOUT_ASPECT_FACTOR ) ); + t->outWidth = MIN( t->outWidth, t->outWidthMax ); + t->outWidth = MAX( 16, t->outWidth ); + } +} + +static 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 + { + HBLog( "GetCPUCount: sscanf() failed" ); + } + } + else + { + HBLog( "GetCPUCount: fgets() failed" ); + } + fclose( info ); + } + else + { + HBLog( "GetCPUCount: popen() failed" ); + } + +#elif defined( SYS_LINUX ) + FILE * info; + char buffer[256]; + + if( ( info = popen( "grep -c '^processor' /proc/cpuinfo", "r" ) ) ) + { + if( fgets( buffer, 256, info ) ) + { + int count; + if( sscanf( buffer, "%d", &count ) == 1 ) + { + CPUCount = count; + } + else + { + HBLog( "GetCPUCount: sscanf() failed" ); + } + } + else + { + HBLog( "GetCPUCount: fgets() failed" ); + } + fclose( info ); + } + else + { + HBLog( "GetCPUCount: fopen() failed" ); + } + +#elif defined( SYS_CYGWIN ) + /* TODO */ + CPUCount = 1; + +#endif + CPUCount = MAX( 1, CPUCount ); + CPUCount = MIN( CPUCount, 8 ); + + return CPUCount; +} + diff --git a/core/HandBrake.h b/core/HandBrake.h new file mode 100644 index 000000000..35ec0fc0a --- /dev/null +++ b/core/HandBrake.h @@ -0,0 +1,55 @@ +/* $Id: HandBrake.h,v 1.3 2003/11/06 13:03:19 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_HANDBRAKE_H +#define HB_HANDBRAKE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "Utils.h" + +/* Init libhb. Set debug to 0 to see no output, 1 to see all libhb logs. + Set cpuCount to 0 if you want libhb to autodetect */ +HBHandle * HBInit( int debug, int cpuCount ); + +/* Fills the HBStatus * argument with infos about the current status. + Returns 1 if mode has changed, 0 otherwise */ +int HBGetStatus( HBHandle *, HBStatus * ); + +/* Launch a thread which scans the specified device and title. Use + title = 0 to scan all titles. Returns immediately */ +void HBScanDevice( HBHandle *, char * device, int title ); + +/* Start ripping the specified title with specified audio tracks. + Returns immediatly */ +void HBStartRip( HBHandle *, HBTitle *, HBAudio *, HBAudio * ); + +/* Suspend rip. Returns immediatly */ +void HBPauseRip( HBHandle * ); + +/* Resume rip. Returns immediatly */ +void HBResumeRip( HBHandle * ); + +/* Cancel rip. Returns immediatly */ +void HBStopRip( HBHandle * ); + +/* Calculate preview for the specified picture of the specified title, + taking care of the current cropping & scaling settings. Returns a + pointer to raw RGBA data. It includes the white border around the + picture, so the size of the picture is ( maxWidth + 2 ) x + ( maxHeight + 2 ) */ +uint8_t * HBGetPreview( HBHandle *, HBTitle *, int picture ); + +/* Clean up things */ +void HBClose( HBHandle ** ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/core/HandBrakeInternal.h b/core/HandBrakeInternal.h new file mode 100644 index 000000000..7c10512c9 --- /dev/null +++ b/core/HandBrakeInternal.h @@ -0,0 +1,35 @@ +/* $Id: HandBrakeInternal.h,v 1.2 2003/11/04 15:44:24 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_HANDBRAKE_INTERNAL_H +#define HB_HANDBRAKE_INTERNAL_H + +#include "HandBrake.h" + +/* Called by HBScan to tell the GUI how far we are */ +void HBScanning( HBHandle *, int title ); + +/* Called by HBScan. titleList is a list of all valid titles which + should be shown on the interface */ +void HBScanDone( HBHandle *, HBList * titleList ); + +/* Used to create temporary files (/tmp/HB.pid.whatever) */ +int HBGetPid( HBHandle * ); + +/* Called by every thread involved in the rip process. Returns + immediately is rip isn't paused, blocks if it is */ +void HBCheckPaused( HBHandle * ); + +/* Called by the decoders when the last packet is being proceeded */ +void HBDone( HBHandle * ); + +/* Called by the video encoder to update the GUI progress */ +void HBPosition( HBHandle *, float ); + +/* Called by any thread which couldn't continue and ask to stop */ +void HBErrorOccured( HBHandle *, HBError ); + +#endif diff --git a/core/Languages.h b/core/Languages.h index 21a5e1487..7949688c9 100644 --- a/core/Languages.h +++ b/core/Languages.h @@ -1,7 +1,7 @@ -/* $Id: Languages.h,v 1.2 2003/09/30 14:38:15 titer Exp $ +/* $Id: Languages.h,v 1.1 2003/11/03 12:08:01 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #ifndef HB_LANGUAGES_H @@ -14,7 +14,7 @@ typedef struct iso639_lang_t char * iso639_1; /* ISO-639-1 (2 characters) code */ } iso639_lang_t; -iso639_lang_t languages[] = +static iso639_lang_t languages[] = { { "Afar", "", "aa" }, { "Abkhazian", "", "ab" }, { "Afrikaans", "", "af" }, diff --git a/core/MadDec.c b/core/MadDec.c new file mode 100644 index 000000000..deecfeebd --- /dev/null +++ b/core/MadDec.c @@ -0,0 +1,9 @@ +/* $Id: MadDec.c,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "MadDec.h" +#include "Fifo.h" + diff --git a/core/MadDec.h b/core/MadDec.h new file mode 100644 index 000000000..b1624338f --- /dev/null +++ b/core/MadDec.h @@ -0,0 +1,15 @@ +/* $Id: MadDec.h,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_MAD_DEC_H +#define HB_MAD_DEC_H + +#include "HandBrakeInternal.h" + +HBMadDec * HBMadDecInit( HBHandle *, HBAudio * ); +void HBMadDecClose( HBMadDec * ); + +#endif diff --git a/core/Manager.cpp b/core/Manager.cpp deleted file mode 100644 index 908aa08fd..000000000 --- a/core/Manager.cpp +++ /dev/null @@ -1,652 +0,0 @@ -/* $Id: Manager.cpp,v 1.70 2003/10/16 13:36:17 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#include "Ac3Decoder.h" -#include "AviMuxer.h" -#include "DVDReader.h" -#include "Fifo.h" -#include "Manager.h" -#include "Mp3Encoder.h" -#include "Mpeg2Decoder.h" -#include "Mpeg4Encoder.h" -#include "MpegDemux.h" -#include "Resizer.h" -#include "Scanner.h" -#include "Worker.h" - -#include <ffmpeg/avcodec.h> - -/* Public methods */ - -HBManager::HBManager( bool debug, int cpuCount ) - : HBThread( "manager", HB_NORMAL_PRIORITY ) -{ - /* See Log() in Common.cpp */ - if( debug ) - { - putenv( "HB_DEBUG=1" ); - } - - /* Check CPU count */ - if( !cpuCount ) - { - fCPUCount = GetCPUCount(); - Log( "HBManager::HBManager: %d CPU%s detected", fCPUCount, - ( fCPUCount > 1 ) ? "s" : "" ); - } - else - { - 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" : "" ); - } - - /* 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 */ - fStatusLock->Lock(); - if( fStatus.fMode == HB_MODE_ENCODING ) - { - fStatusLock->Unlock(); - - StopRip(); - while( fStopRip ) - { - Snooze( 10000 ); - } - } - else - { - fStatusLock->Unlock(); - } - - /* Stop scanning if needed */ - if( fScanner ) - { - delete fScanner; - } - - /* Remove temp files */ - char command[1024]; memset( command, 0, 1024 ); - sprintf( command, "rm -f /tmp/HB.%d.*", GetPid() ); - system( command ); - - delete fStatusLock; -} - -void HBManager::DoWork() -{ - while( !fDie ) - { - if( fStopScan ) - { - /* Destroy the thread */ - delete fScanner; - fScanner = NULL; - - /* Update interface */ - fStatusLock->Lock(); - if( fStatus.fTitleList && fStatus.fTitleList->CountItems() ) - { - fStatus.fMode = HB_MODE_READY_TO_RIP; - } - else - { - fStatus.fMode = HB_MODE_INVALID_VOLUME; - } - fNeedUpdate = true; - fStatusLock->Unlock(); - - fStopScan = false; - } - - if( fStopRip || fError || fRipDone ) - { - if( fRipDone ) - { - /* Wait a bit */ - while( fCurTitle->fPSFifo->Size() ) - { - Snooze( 10000 ); - } - while( fCurTitle->fMpeg2Fifo->Size() && - ( !fCurAudio1 || fCurAudio1->fAc3Fifo->Size() ) && - ( !fCurAudio2 || fCurAudio2->fAc3Fifo->Size() ) ) - { - Snooze( 10000 ); - } - Snooze( 500000 ); - } - else - { - fStatusLock->Lock(); - fStatus.fMode = HB_MODE_STOPPING; - fNeedUpdate = true; - fStatusLock->Unlock(); - } - - /* Stop threads */ - delete fCurTitle->fDVDReader; - delete fCurTitle->fAviMuxer; - for( int i = 0; i < fCPUCount; i++ ) - { - delete fCurTitle->fWorkers[i]; - } - - /* Clean up */ - delete fCurTitle->fMpegDemux; - delete fCurTitle->fMpeg2Decoder; - delete fCurTitle->fResizer; - delete fCurTitle->fMpeg4Encoder; - - if( fCurAudio1 ) - { - delete fCurAudio1->fAc3Decoder; - delete fCurAudio1->fMp3Encoder; - } - - if( fCurAudio2 ) - { - delete fCurAudio2->fAc3Decoder; - delete fCurAudio2->fMp3Encoder; - } - - /* Destroy fifos */ - 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; - } - - /* 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 ); - } -} - -bool HBManager::NeedUpdate() -{ - fStatusLock->Lock(); - if( fNeedUpdate ) - { - fNeedUpdate = false; - fStatusLock->Unlock(); - return true; - } - fStatusLock->Unlock(); - - return false; -} - -HBStatus HBManager::GetStatus() -{ - fStatusLock->Lock(); - HBStatus status = fStatus; - fStatusLock->Unlock(); - - return status; -} - -void HBManager::ScanVolumes( char * device ) -{ - if( !( fStatus.fMode & - ( HB_MODE_NEED_VOLUME | HB_MODE_INVALID_VOLUME ) ) ) - { - Log( "HBManager::ScanVolumes : current mode is %d, aborting", - fStatus.fMode ); - return; - } - - fScanner = new HBScanner( this, device ); - - 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, - HBAudio * audio2, char * file ) -{ - if( !title || !file ) - { - Log( "HBManager::StartRip : error (title = %p, file = %s)", - title, file ); - return; - } - - if( !( fStatus.fMode & ( HB_MODE_READY_TO_RIP | HB_MODE_DONE | - HB_MODE_CANCELED | HB_MODE_ERROR ) ) ) - { - Log( "HBManager::StartRip : current mode is %d, aborting", - fStatus.fMode ); - return; - } - - FixPictureSettings( title ); - - Log( "HBManager::StartRip:" ); - 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", - 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 ); - } - if( audio2 ) - { - Log( "- audio 2: lang = %s (%x), bitrate = %d", - audio2->fDescription, audio2->fId, audio2->fOutBitrate ); - } - - /* 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 ); - } - - /* 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 ); - if( audio1 ) - { - audio1->fAc3Decoder = new HBAc3Decoder( this, audio1 ); - audio1->fMp3Encoder = new HBMp3Encoder( this, audio1 ); - } - if( audio2 ) - { - audio2->fAc3Decoder = new HBAc3Decoder( this, audio2 ); - audio2->fMp3Encoder = new HBMp3Encoder( this, 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++ ) - { - 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; - fStatus.fFrames = 0; - fStatus.fStartDate = 0; - fStatus.fRemainingTime = 0; - fStatus.fSuspendDate = 0; - fNeedUpdate = true; - fStatusLock->Unlock(); -} - -void HBManager::SuspendRip() -{ - if( fStatus.fMode != HB_MODE_ENCODING ) - { - Log( "HBManager::SuspendRip : current mode is %d, aborting", - fStatus.fMode ); - return; - } - - fCurTitle->fDVDReader->Suspend(); - fCurTitle->fAviMuxer->Suspend(); - for( int i = 0; i < fCPUCount; i++ ) - { - fCurTitle->fWorkers[i]->Suspend(); - } - - fStatusLock->Lock(); - fStatus.fMode = HB_MODE_SUSPENDED; - fStatus.fSuspendDate = GetDate(); - fNeedUpdate = true; - fStatusLock->Unlock(); -} - -void HBManager::ResumeRip() -{ - if( fStatus.fMode != HB_MODE_SUSPENDED ) - { - Log( "HBManager::ResumeRip : current mode is %d, aborting", - fStatus.fMode ); - return; - } - - fCurTitle->fDVDReader->Resume(); - fCurTitle->fAviMuxer->Resume(); - for( int i = 0; i < fCPUCount; i++ ) - { - fCurTitle->fWorkers[i]->Resume(); - } - - fStatusLock->Lock(); - fStatus.fMode = HB_MODE_ENCODING; - fStatus.fStartDate += GetDate() - fStatus.fSuspendDate; - fNeedUpdate = true; - fStatusLock->Unlock(); -} - -void HBManager::StopRip() -{ - if( !( fStatus.fMode & ( HB_MODE_ENCODING | HB_MODE_SUSPENDED ) ) ) - { - Log( "HBManager::StopRip : current mode is %d, aborting", - fStatus.fMode ); - return; - } - - /* Stop the threads */ - fStopRip = true; -} - -#define fInWidth title->fInWidth -#define fInHeight title->fInHeight -#define fAspect title->fAspect -#define fDeinterlace title->fDeinterlace -#define fOutWidth title->fOutWidth -#define fOutHeight title->fOutHeight -#define fOutWidthMax title->fOutWidthMax -#define fOutHeightMax title->fOutHeightMax -#define fTopCrop title->fTopCrop -#define fBottomCrop title->fBottomCrop -#define fLeftCrop title->fLeftCrop -#define fRightCrop title->fRightCrop - -void HBManager::FixPictureSettings( HBTitle * title ) -{ - /* Sanity checks */ - fTopCrop = EVEN( fTopCrop ); - fBottomCrop = EVEN( fBottomCrop ); - fLeftCrop = EVEN( fLeftCrop ); - fRightCrop = EVEN( fRightCrop ); - - fOutWidth = MIN( fOutWidth, fOutWidthMax ); - fOutWidth = MAX( 16, fOutWidth ); - - fOutHeight = MULTIPLE_16( (uint64_t) fOutWidth * fInWidth * - ( fInHeight - fTopCrop - fBottomCrop ) * - VOUT_ASPECT_FACTOR / - ( (uint64_t) fInHeight * - ( fInWidth - fLeftCrop - fRightCrop ) * - fAspect ) ); - fOutHeight = MAX( 16, fOutHeight ); - - if( fOutHeight > fOutHeightMax ) - { - fOutHeight = fOutHeightMax; - fOutWidth = MULTIPLE_16( (uint64_t) fOutHeight * fInHeight * - ( fInWidth - fLeftCrop - fRightCrop ) * - fAspect / - ( (uint64_t) fInWidth * - ( fInHeight - fTopCrop - fBottomCrop ) * - VOUT_ASPECT_FACTOR ) ); - fOutWidth = MIN( fOutWidth, fOutWidthMax ); - fOutWidth = MAX( 16, fOutWidth ); - } -} - -uint8_t * HBManager::GetPreview( HBTitle * title, uint32_t image ) -{ - FixPictureSettings( title ); - - AVPicture pic1, pic2, pic3, pic4; - uint8_t * buf1, * buf2, * buf3, * buf4; - - /* Original YUV picture */ - buf1 = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 ); - avpicture_fill( &pic1, buf1, PIX_FMT_YUV420P, fInWidth, - fInHeight ); - - /* Deinterlaced YUV picture */ - buf2 = (uint8_t*) malloc( 3 * fInWidth * fInHeight / 2 ); - avpicture_fill( &pic2, buf2, PIX_FMT_YUV420P, - fInWidth, fInHeight ); - - /* Resized YUV picture */ - buf3 = (uint8_t*) malloc( 3 * fOutWidth * fOutHeight / 2 ); - avpicture_fill( &pic3, buf3, PIX_FMT_YUV420P, fOutWidth, - fOutHeight ); - - /* Resized RGB picture ) */ - buf4 = (uint8_t*) malloc( 4 * fOutWidth * fOutHeight ); - avpicture_fill( &pic4, buf4, PIX_FMT_RGBA32, fOutWidth, - fOutHeight ); - - /* Get the original image from the temp file */ - char fileName[1024]; memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.%x.%d", GetPid(), (uint32_t) title, - image); - FILE * file = fopen( fileName, "r" ); - fread( buf1, 3 * fInWidth * fInHeight / 2, 1, file ); - fclose( file ); - - /* Deinterlace if needed, and resize */ - ImgReSampleContext * resampleContext = - img_resample_full_init( fOutWidth, fOutHeight, - fInWidth, fInHeight, - fTopCrop, fBottomCrop, - fLeftCrop, fRightCrop ); - if( fDeinterlace ) - { - avpicture_deinterlace( &pic2, &pic1, PIX_FMT_YUV420P, - fInWidth, fInHeight ); - img_resample( resampleContext, &pic3, &pic2 ); - } - else - { - img_resample( resampleContext, &pic3, &pic1 ); - } - - /* Convert to RGB */ - img_convert( &pic4, PIX_FMT_RGBA32, &pic3, PIX_FMT_YUV420P, - fOutWidth, fOutHeight ); - - /* Create the final preview */ - uint8_t * preview = (uint8_t*) malloc( 4 * ( fOutWidthMax + 2 ) * - ( fOutHeightMax + 2 ) ); - - /* Blank it */ - memset( preview, 0, - 4 * ( fOutWidthMax + 2 ) * ( fOutHeightMax + 2 ) ); - - /* Draw the picture (centered) and draw the cropping zone */ - uint32_t leftOffset = 1 + ( fOutWidthMax - fOutWidth ) / 2; - uint32_t topOffset = 1 + ( fOutHeightMax - fOutHeight ) / 2; - - memset( preview + 4 * ( ( fOutWidthMax + 2 ) * ( topOffset - 1 ) + - leftOffset - 1 ), - 0xFF, 4 * ( fOutWidth + 2 ) ); - - for( uint32_t i = 0; i < fOutHeight; i++ ) - { - memset( preview + 4 * ( ( fOutWidthMax + 2 ) * - ( i + topOffset ) + leftOffset - 1 ), - 0xFF, 4 ); - memcpy( preview + 4 * ( ( fOutWidthMax + 2 ) * - ( i + topOffset ) + leftOffset ), - buf4 + 4 * fOutWidth * i, - 4 * fOutWidth ); - memset( preview + 4 * ( ( fOutWidthMax + 2 ) * - ( i + topOffset ) + leftOffset + - fOutWidth ), - 0xFF, 4 ); - } - - memset( preview + 4 * ( ( fOutWidthMax + 2 ) * - ( topOffset + fOutHeight ) + - leftOffset - 1 ), - 0xFF, 4 * ( fOutWidth + 2 ) ); - - /* Free memory */ - free( buf1 ); - free( buf2 ); - free( buf3 ); - free( buf4 ); - - return preview; -} - -#undef fInWidth -#undef fInHeight -#undef fAspect -#undef fDeinterlace -#undef fOutWidth -#undef fOutHeight -#undef fOutWidthMax -#undef fOutHeightMax -#undef fTopCrop -#undef fBottomCrop -#undef fLeftCrop -#undef fRightCrop - -void HBManager::Scanning( char * volume, int title ) -{ - fStatusLock->Lock(); - fStatus.fMode = HB_MODE_SCANNING; - fStatus.fScannedVolume = volume; - fStatus.fScannedTitle = title; - fNeedUpdate = true; - fStatusLock->Unlock(); -} - -void HBManager::ScanDone( HBList * titleList ) -{ - fStatus.fTitleList = titleList;; - fStopScan = true; -} - -/* Called by the DVD reader */ -void HBManager::Done() -{ - fRipDone = true; -} - -void HBManager::Error( HBError error ) -{ - if( fStatus.fMode != HB_MODE_ENCODING ) - { - return; - } - - fStatus.fError = error; - fError = true; -} - -void HBManager::SetPosition( float pos ) -{ - if( !fStatus.fStartDate ) - { - fStatus.fStartDate = GetDate(); - } - - fStatus.fFrames++; - - if( ( pos - fStatus.fPosition ) * 10000 < 1 ) - { - return; - } - - fStatusLock->Lock(); - fStatus.fPosition = pos; - fStatus.fFrameRate = (float) fStatus.fFrames / - ( ( (float) ( GetDate() - fStatus.fStartDate ) ) / 1000000 ) ; - fStatus.fRemainingTime = - (uint32_t) ( (float) ( GetDate() - fStatus.fStartDate ) * - ( 1 - fStatus.fPosition ) / - ( 1000000 * fStatus.fPosition ) ); - fNeedUpdate = true; - fStatusLock->Unlock(); -} - diff --git a/core/Manager.h b/core/Manager.h deleted file mode 100644 index dc885e5f5..000000000 --- a/core/Manager.h +++ /dev/null @@ -1,64 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MANAGER_H -#define HB_MANAGER_H - -#include "Common.h" -#include "Thread.h" - -class HBManager : public HBThread -{ - public: - HBManager( bool debug = false, - int cpuCount = 0 ); - ~HBManager(); - void DoWork(); - - /* Methods called by the interface */ - bool NeedUpdate(); - HBStatus GetStatus(); - void ScanVolumes( char * device ); - void StartRip( HBTitle * title, HBAudio * audio1, - HBAudio * audio2, char * file ); - void SuspendRip(); - void ResumeRip(); - void StopRip(); - uint8_t * GetPreview( HBTitle * title, uint32_t image ); - - /* Methods called by the working threads */ - void Scanning( char * volume, int title ); - void ScanDone( HBList * titleList ); - void Done(); - void Error( HBError error ); - void SetPosition( float pos ); - - private: - void FixPictureSettings( HBTitle * title ); - - int fPid; - int fCPUCount; - - /* Booleans used in DoWork() */ - bool fStopScan; - volatile bool fStopRip; - bool fRipDone; - bool fError; - - /* Scanner thread */ - HBScanner * fScanner; - - /* Status infos */ - HBLock * fStatusLock; - bool fNeedUpdate; - HBStatus fStatus; - - HBTitle * fCurTitle; - HBAudio * fCurAudio1; - HBAudio * fCurAudio2; -}; - -#endif diff --git a/core/Mp3Enc.c b/core/Mp3Enc.c new file mode 100644 index 000000000..70693467f --- /dev/null +++ b/core/Mp3Enc.c @@ -0,0 +1,281 @@ +/* $Id: Mp3Enc.c,v 1.5 2003/11/07 21:52:57 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Fifo.h" +#include "Mp3Enc.h" +#include "Work.h" + +#include <lame/lame.h> + +/* Local prototypes */ +static int Mp3EncWork( HBWork * ); +static int GetBytes( HBMp3Enc * ); + +struct HBMp3Enc +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBAudio * audio; + lame_global_flags * globalFlags; + HBBuffer * rawBuffer; + int rawBufferPos; + float position; + int samplesNeeded; + int samplesGot; + float * left; + float * right; + HBBuffer * mp3Buffer; +}; + +HBMp3Enc * HBMp3EncInit( HBHandle * handle, HBAudio * audio ) +{ + HBMp3Enc * m; + if( !( m = malloc( sizeof( HBMp3Enc ) ) ) ) + { + HBLog( "HBMp3EncInit: malloc() failed, gonna crash" ); + return NULL; + } + + m->name = strdup( "Mp3Enc" ); + m->work = Mp3EncWork; + + m->handle = handle; + m->audio = audio; + m->globalFlags = NULL; + m->rawBuffer = NULL; + m->rawBufferPos = 0; + m->position = 0.0; + m->samplesNeeded = 0; + m->samplesGot = 0; + m->left = NULL; + m->right = NULL; + m->mp3Buffer = NULL; + + return m; +} + +void HBMp3EncClose( HBMp3Enc ** _m ) +{ + HBMp3Enc * m = *_m; + + if( m->globalFlags ) lame_close( m->globalFlags ); + if( m->rawBuffer ) HBBufferClose( &m->rawBuffer ); + if( m->left ) free( m->left ); + if( m->right ) free( m->right ); + if( m->mp3Buffer ) HBBufferClose( &m->mp3Buffer ); + free( m->name ); + free( m ); + + *_m = NULL; +} + +static int Mp3EncWork( HBWork * w ) +{ + HBMp3Enc * m = (HBMp3Enc*) w; + HBAudio * audio = m->audio; + + HBBuffer * mp3Buffer; + int ret; + + int didSomething = 0; + + if( !m->globalFlags ) + { + int i; + + /* Get a first buffer so we know that audio->inSampleRate is + correct */ + if( ( m->rawBuffer = HBFifoPop( audio->rawFifo ) ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + m->rawBufferPos = 0; + m->position = m->rawBuffer->position; + + /* The idea is to have exactly one mp3 frame (i.e. 1152 samples) by + output buffer. As we are resampling from inSampleRate to + outSampleRate, we will give ( 1152 * inSampleRate ) / + ( 2 * outSampleRate ) samples to libmp3lame so we are sure we + will never get more than 1 frame at a time */ + m->samplesNeeded = 1152 * audio->inSampleRate / + audio->outSampleRate / 2; + + HBLog( "HBMp3Enc: opening lame (%d->%d Hz, %d kbps)", + audio->inSampleRate, audio->outSampleRate, + audio->outBitrate ); + m->globalFlags = lame_init(); + lame_set_in_samplerate( m->globalFlags, audio->inSampleRate ); + lame_set_out_samplerate( m->globalFlags, audio->outSampleRate ); + lame_set_brate( m->globalFlags, audio->outBitrate ); + + if( lame_init_params( m->globalFlags ) == -1 ) + { + HBLog( "HBMp3Enc: lame_init_params() failed" ); + HBErrorOccured( m->handle, HB_ERROR_MP3_INIT ); + return didSomething; + } + + m->left = malloc( m->samplesNeeded * sizeof( float ) ); + m->right = malloc( m->samplesNeeded * sizeof( float ) ); + + if( !m->left || !m->right ) + { + HBLog( "HBMp3Enc: malloc() failed, gonna crash" ); + } + + for( i = 0; i < m->samplesNeeded; i++ ) + { + m->left[i] = 0.0; + m->right[i] = 0.0; + } + } + + /* Push encoded buffer */ + if( m->mp3Buffer ) + { + if( HBFifoPush( audio->mp3Fifo, &m->mp3Buffer ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + } + + /* A/V synchro fix in case audio doesn't start at the same time + than video */ + if( audio->delay > 0 ) + { + /* Audio starts later - insert some silence */ + int length = m->samplesNeeded * 1000 / audio->inSampleRate; + + if( audio->delay > length ) + { + HBLog( "HBMp3Enc: adding %d ms of silence", length ); + m->samplesGot = m->samplesNeeded; + audio->delay -= length; + } + else + { + audio->delay = 0; + } + } + else if( audio->delay < 0 ) + { + /* Audio starts sooner - trash some */ + int length = m->samplesNeeded * 1000 / audio->inSampleRate; + + if( - audio->delay > length ) + { + if( GetBytes( m ) ) + { + didSomething = 1; + HBLog( "HBMp3Enc: trashing %d ms", length ); + m->samplesGot = 0; + audio->delay += length; + return didSomething; + } + else + { + return didSomething; + } + } + else + { + audio->delay = 0; + } + } + + /* Get new samples */ + if( GetBytes( m ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + m->samplesGot = 0; + + mp3Buffer = HBBufferInit( LAME_MAXMP3BUFFER ); + ret = lame_encode_buffer_float( m->globalFlags, m->left, + m->right, m->samplesNeeded, + mp3Buffer->data, + mp3Buffer->size ); + + if( ret < 0 ) + { + /* Error */ + HBLog( "HBMp3Enc: lame_encode_buffer_float() failed (%d)", + ret ); + HBErrorOccured( m->handle, HB_ERROR_MP3_ENCODE ); + HBBufferClose( &mp3Buffer ); + } + else if( ret == 0 ) + { + /* No error, but nothing encoded */ + HBBufferClose( &mp3Buffer ); + } + else + { + /* Encoding was successful */ + mp3Buffer->size = ret; + mp3Buffer->keyFrame = 1; + mp3Buffer->position = m->position; + + m->mp3Buffer = mp3Buffer; + } + + return didSomething; +} + +static int GetBytes( HBMp3Enc * m ) +{ + while( m->samplesGot < m->samplesNeeded ) + { + int i; + + if( !m->rawBuffer ) + { + if( !( m->rawBuffer = HBFifoPop( m->audio->rawFifo ) ) ) + { + return 0; + } + + m->rawBufferPos = 0; + m->position = m->rawBuffer->position; + } + + i = MIN( m->samplesNeeded - m->samplesGot, + ( m->rawBuffer->size / 2 - + m->rawBufferPos ) / sizeof( float ) ); + + memcpy( m->left + m->samplesGot, + m->rawBuffer->data + m->rawBufferPos, + i * sizeof( float ) ); + memcpy( m->right + m->samplesGot, + m->rawBuffer->data + m->rawBuffer->size / 2 + + m->rawBufferPos, + i * sizeof( float ) ); + + m->samplesGot += i; + m->rawBufferPos += i * sizeof( float ); + + if( m->rawBufferPos == m->rawBuffer->size / 2 ) + { + HBBufferClose( &m->rawBuffer ); + } + } + + return 1; +} diff --git a/core/Mp3Enc.h b/core/Mp3Enc.h new file mode 100644 index 000000000..db02f4f44 --- /dev/null +++ b/core/Mp3Enc.h @@ -0,0 +1,15 @@ +/* $Id: Mp3Enc.h,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_MP3_ENCODER_H +#define HB_MP3_ENCODER_H + +#include "HandBrakeInternal.h" + +HBMp3Enc * HBMp3EncInit( HBHandle *, HBAudio * ); +void HBMp3EncClose( HBMp3Enc ** ); + +#endif diff --git a/core/Mp3Encoder.cpp b/core/Mp3Encoder.cpp deleted file mode 100644 index 96ae8c568..000000000 --- a/core/Mp3Encoder.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* $Id: Mp3Encoder.cpp,v 1.14 2003/10/14 14:35:20 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 "Mp3Encoder.h" -#include "Manager.h" -#include "Fifo.h" - -#include <lame/lame.h> - -HBMp3Encoder::HBMp3Encoder( HBManager * manager, HBAudio * 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; -} - -bool HBMp3Encoder::Work() -{ - if( !Lock() ) - { - return false; - } - - if( !fInitDone ) - { - /* 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; - } - - fLeftSamples = (float*) malloc( fCount * sizeof( float ) ); - fRightSamples = (float*) malloc( fCount * sizeof( float ) ); - - fInitDone = true; - } - - if( fMp3Buffer ) - { - if( fAudio->fMp3Fifo->Push( fMp3Buffer ) ) - { - fMp3Buffer = NULL; - } - else - { - Unlock(); - return false; - } - } - - /* Get new samples */ - if( GetSamples() ) - { - fSamplesNb = 0; - - fMp3Buffer = new HBBuffer( LAME_MAXMP3BUFFER ); - int ret = lame_encode_buffer_float( fGlobalFlags, fLeftSamples, - fRightSamples, fCount, - fMp3Buffer->fData, - fMp3Buffer->fSize ); - - if( ret < 0 ) - { - 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 */ - fMp3Buffer->fSize = ret; - fMp3Buffer->fKeyFrame = true; - fMp3Buffer->fPosition = fPosition; - } - else - { - delete fMp3Buffer; - fMp3Buffer = NULL; - } - } - else - { - Unlock(); - return false; - } - - Unlock(); - return true; -} - -bool HBMp3Encoder::Lock() -{ - fLock->Lock(); - if( fUsed ) - { - fLock->Unlock(); - return false; - } - fUsed = true; - fLock->Unlock(); - return true; -} - -void HBMp3Encoder::Unlock() -{ - fLock->Lock(); - fUsed = false; - fLock->Unlock(); -} - -bool HBMp3Encoder::GetSamples() -{ - while( fSamplesNb < fCount ) - { - if( !fRawBuffer ) - { - if( !( fRawBuffer = fAudio->fRawFifo->Pop() ) ) - { - return false; - } - - fPosInBuffer = 0; - fPosition = fRawBuffer->fPosition; - } - - int willCopy = MIN( fCount - fSamplesNb, 6 * 256 - fPosInBuffer ); - - memcpy( fLeftSamples + fSamplesNb, - (float*) fRawBuffer->fData + fPosInBuffer, - willCopy * sizeof( float ) ); - memcpy( fRightSamples + fSamplesNb, - (float*) fRawBuffer->fData + 6 * 256 + fPosInBuffer, - willCopy * sizeof( float ) ); - - fSamplesNb += willCopy; - fPosInBuffer += willCopy; - - if( fPosInBuffer == 6 * 256 ) - { - delete fRawBuffer; - fRawBuffer = NULL; - } - } - - return true; -} diff --git a/core/Mp3Encoder.h b/core/Mp3Encoder.h deleted file mode 100644 index fb8348961..000000000 --- a/core/Mp3Encoder.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MP3_ENCODER_H -#define HB_MP3_ENCODER_H - -#include "Common.h" - -class HBMp3Encoder -{ - public: - HBMp3Encoder( HBManager * manager, - HBAudio * audio ); - bool Work(); - - private: - 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/Mpeg2Dec.c b/core/Mpeg2Dec.c new file mode 100644 index 000000000..d6ce22b3f --- /dev/null +++ b/core/Mpeg2Dec.c @@ -0,0 +1,195 @@ +/* $Id: Mpeg2Dec.c,v 1.3 2003/11/06 12:33:11 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Fifo.h" +#include "Mpeg2Dec.h" +#include "Work.h" + +#include <mpeg2dec/mpeg2.h> + +/* Local prototypes */ +static int Mpeg2DecWork( HBWork * ); + +struct HBMpeg2Dec +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBTitle * title; + HBList * rawBufferList; + int pass; + mpeg2dec_t * libmpeg2; + const mpeg2_info_t * info; + int lateField; +}; + +HBMpeg2Dec * HBMpeg2DecInit( HBHandle * handle, HBTitle * title ) +{ + HBMpeg2Dec * m ; + if( !( m = malloc( sizeof( HBMpeg2Dec ) ) ) ) + { + HBLog( "HBMpeg2Dec: malloc() failed, gonna crash" ); + return NULL; + } + + m->name = strdup( "Mpeg2Dec" ); + m->work = Mpeg2DecWork; + + m->handle = handle; + m->title = title; + + m->rawBufferList = HBListInit(); + m->pass = 42; + m->libmpeg2 = NULL; + m->info = NULL; + m->lateField = 0; + + return m; +} + +void HBMpeg2DecClose( HBMpeg2Dec ** _m ) +{ + HBBuffer * buffer; + + HBMpeg2Dec * m = *_m; + + if( m->libmpeg2 ) + { + HBLog( "HBMpeg2Dec: closing libmpeg2 (pass %d)", m->pass ); + mpeg2_close( m->libmpeg2 ); + } + while( ( buffer = HBListItemAt( m->rawBufferList, 0 ) ) ) + { + HBListRemove( m->rawBufferList, buffer ); + HBBufferClose( &buffer ); + } + HBListClose( &m->rawBufferList ); + free( m->name ); + free( m ); + + *_m = NULL; +} + +static int Mpeg2DecWork( HBWork * w ) +{ + HBMpeg2Dec * m = (HBMpeg2Dec*) w; + HBTitle * title = m->title; + HBBuffer * mpeg2Buffer; + HBBuffer * rawBuffer; + HBBuffer * tmpBuffer; + mpeg2_state_t state; + + int didSomething = 0; + + /* Push decoded buffers */ + while( ( rawBuffer = (HBBuffer*) + HBListItemAt( m->rawBufferList, 0 ) ) ) + { + tmpBuffer = rawBuffer; + if( HBFifoPush( title->rawFifo, &rawBuffer ) ) + { + didSomething = 1; + HBListRemove( m->rawBufferList, tmpBuffer ); + } + else + { + return didSomething; + } + } + + /* Get a new buffer to decode */ + if( ( mpeg2Buffer = HBFifoPop( title->mpeg2Fifo ) ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + /* Init or re-init if needed */ + if( mpeg2Buffer->pass != m->pass ) + { + if( m->libmpeg2 ) + { + HBLog( "HBMpeg2Dec: closing libmpeg2 (pass %d)", m->pass ); + mpeg2_close( m->libmpeg2 ); + } + + m->pass = mpeg2Buffer->pass; + + HBLog( "HBMpeg2Dec: opening libmpeg2 (pass %d)", m->pass ); + m->libmpeg2 = mpeg2_init(); + m->info = mpeg2_info( m->libmpeg2 ); + m->lateField = 0; + } + + /* Decode */ + mpeg2_buffer( m->libmpeg2, mpeg2Buffer->data, + mpeg2Buffer->data + mpeg2Buffer->size ); + + for( ;; ) + { + state = mpeg2_parse( m->libmpeg2 ); + + if( state == STATE_BUFFER ) + { + break; + } + else if( ( state == STATE_SLICE || state == STATE_END ) && + m->info->display_fbuf ) + { + rawBuffer = HBBufferInit( 3 * title->inWidth * + title->outWidth ); + + /* TODO: make libmpeg2 write directly in our buffer */ + memcpy( rawBuffer->data, m->info->display_fbuf->buf[0], + title->inWidth * title->inHeight ); + memcpy( rawBuffer->data + title->inWidth * title->inHeight, + m->info->display_fbuf->buf[1], + title->inWidth * title->inHeight / 4 ); + memcpy( rawBuffer->data + title->inWidth * title->inHeight + + title->inWidth * title->inHeight / 4, + m->info->display_fbuf->buf[2], + title->inWidth * title->inHeight / 4 ); + + rawBuffer->position = mpeg2Buffer->position; + rawBuffer->pass = mpeg2Buffer->pass; + + HBListAdd( m->rawBufferList, rawBuffer ); + + /* NTSC pulldown kludge */ + if( m->info->display_picture->nb_fields == 3 ) + { + if( m->lateField ) + { + tmpBuffer = HBBufferInit( rawBuffer->size ); + tmpBuffer->position = rawBuffer->position; + tmpBuffer->pass = rawBuffer->pass; + tmpBuffer->last = rawBuffer->last; + memcpy( tmpBuffer->data, rawBuffer->data, + tmpBuffer->size ); + HBListAdd( m->rawBufferList, tmpBuffer ); + } + m->lateField = !m->lateField; + } + } + else if( state == STATE_INVALID ) + { + /* Shouldn't happen on a DVD */ + HBLog( "HBMpeg2Dec: STATE_INVALID" ); + } + } + + if( mpeg2Buffer->last ) + { + HBDone( m->handle ); + } + + HBBufferClose( &mpeg2Buffer ); + + return didSomething; +} diff --git a/core/Mpeg2Dec.h b/core/Mpeg2Dec.h new file mode 100644 index 000000000..af7f18c44 --- /dev/null +++ b/core/Mpeg2Dec.h @@ -0,0 +1,15 @@ +/* $Id: Mpeg2Dec.h,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_MPEG2_DEC_H +#define HB_MPEG2_DEC_H + +#include "HandBrakeInternal.h" + +HBMpeg2Dec * HBMpeg2DecInit( HBHandle *, HBTitle * ); +void HBMpeg2DecClose( HBMpeg2Dec ** ); + +#endif diff --git a/core/Mpeg2Decoder.cpp b/core/Mpeg2Decoder.cpp deleted file mode 100644 index a9b6a5373..000000000 --- a/core/Mpeg2Decoder.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* $Id: Mpeg2Decoder.cpp,v 1.22 2003/10/14 14:35:20 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#include "Mpeg2Decoder.h" -#include "Manager.h" -#include "Fifo.h" - -extern "C" { -#include <mpeg2dec/mpeg2.h> -} -#include <ffmpeg/avcodec.h> - -HBMpeg2Decoder::HBMpeg2Decoder( HBManager * manager, HBTitle * title ) -{ - fManager = manager; - fTitle = title; - - fLock = new HBLock(); - fUsed = false; - - fPass = 42; - fRawBuffer = NULL; - fRawBufferList = new HBList(); - fHandle = NULL; -} - -bool HBMpeg2Decoder::Work() -{ - if( !Lock() ) - { - return false; - } - - /* Push decoded buffers */ - while( ( fRawBuffer = - (HBBuffer*) fRawBufferList->ItemAt( 0 ) ) ) - { - if( fTitle->fRawFifo->Push( fRawBuffer ) ) - { - fRawBufferList->RemoveItem( fRawBuffer ); - } - else - { - Unlock(); - return false; - } - } - - /* Get a new buffer to decode */ - if( ( fMpeg2Buffer = fTitle->fMpeg2Fifo->Pop() ) ) - { - /* (Re)init if needed */ - if( fMpeg2Buffer->fPass != fPass ) - { - fPass = fMpeg2Buffer->fPass; - Init(); - } - - /* Do the job */ - DecodeBuffer(); - } - else - { - Unlock(); - return false; - } - - Unlock(); - return true; -} - -bool HBMpeg2Decoder::Lock() -{ - fLock->Lock(); - if( fUsed ) - { - fLock->Unlock(); - return false; - } - fUsed = true; - fLock->Unlock(); - return true; -} - -void HBMpeg2Decoder::Unlock() -{ - fLock->Lock(); - fUsed = false; - fLock->Unlock(); -} - -void HBMpeg2Decoder::Init() -{ - if( fHandle ) - { - mpeg2_close( fHandle ); - } - - fLateField = false; - - fHandle = mpeg2_init(); -} - -void HBMpeg2Decoder::DecodeBuffer() -{ - const mpeg2_info_t * info = mpeg2_info( fHandle ); - - /* Feed libmpeg2 */ - mpeg2_buffer( fHandle, fMpeg2Buffer->fData, - fMpeg2Buffer->fData + fMpeg2Buffer->fSize ); - - mpeg2_state_t state; - for( ;; ) - { - state = mpeg2_parse( fHandle ); - - if( state == STATE_BUFFER ) - { - break; - } - else if( ( state == STATE_SLICE || state == STATE_END ) && - info->display_fbuf ) - { - fRawBuffer = new HBBuffer( 3 * fTitle->fInWidth * - fTitle->fInHeight / 2 ); - - /* TODO : make libmpeg2 write directly in our buffer */ - memcpy( fRawBuffer->fData, - info->display_fbuf->buf[0], - fTitle->fInWidth * fTitle->fInHeight ); - memcpy( fRawBuffer->fData + fTitle->fInWidth * - fTitle->fInHeight, - info->display_fbuf->buf[1], - fTitle->fInWidth * fTitle->fInHeight / 4 ); - memcpy( fRawBuffer->fData + fTitle->fInWidth * - fTitle->fInHeight + fTitle->fInWidth * - fTitle->fInHeight / 4, - info->display_fbuf->buf[2], - fTitle->fInWidth * fTitle->fInHeight / 4 ); - - fRawBuffer->fPosition = fMpeg2Buffer->fPosition; - fRawBuffer->fPass = fMpeg2Buffer->fPass; - - fRawBufferList->AddItem( fRawBuffer ); - - /* NTSC pulldown kludge */ - if( info->display_picture->nb_fields == 3 ) - { - if( fLateField ) - { - 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; - } - } - else if( state == STATE_INVALID ) - { - /* Shouldn't happen on a DVD */ - Log( "HBMpeg2Decoder: STATE_INVALID" ); - } - } - - delete fMpeg2Buffer; - fMpeg2Buffer = NULL; -} - diff --git a/core/Mpeg2Decoder.h b/core/Mpeg2Decoder.h deleted file mode 100644 index 6e20509a2..000000000 --- a/core/Mpeg2Decoder.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $Id: Mpeg2Decoder.h,v 1.16 2003/10/14 14:35:20 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MPEG2_DECODER_H -#define HB_MPEG2_DECODER_H - -#include "Common.h" - -class HBMpeg2Decoder -{ - public: - HBMpeg2Decoder( HBManager * manager, - HBTitle * title ); - bool Work(); - - private: - bool Lock(); - void Unlock(); - - void Init(); - void DecodeBuffer(); - - HBManager * fManager; - HBTitle * fTitle; - - HBLock * fLock; - bool fUsed; - - uint32_t fPass; - HBBuffer * fMpeg2Buffer; - HBBuffer * fRawBuffer; - HBList * fRawBufferList; - mpeg2dec_t * fHandle; - bool fLateField; -}; - -#endif diff --git a/core/Mpeg4Encoder.cpp b/core/Mpeg4Encoder.cpp deleted file mode 100644 index bf5821a4c..000000000 --- a/core/Mpeg4Encoder.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* $Id: Mpeg4Encoder.cpp,v 1.25 2003/10/14 15:23:56 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#include "Mpeg4Encoder.h" -#include "Manager.h" -#include "Fifo.h" - -#include <ffmpeg/avcodec.h> - -HBMpeg4Encoder::HBMpeg4Encoder( HBManager * manager, HBTitle * title ) -{ - fManager = manager; - fTitle = title; - - fLock = new HBLock(); - fUsed = false; - - fPass = 42; - fMpeg4Buffer = NULL; - fFile = NULL; - fFrame = avcodec_alloc_frame(); - fLog = NULL; -} - -bool HBMpeg4Encoder::Work() -{ - if( !Lock() ) - { - return false; - } - - if( fMpeg4Buffer ) - { - if( fTitle->fMpeg4Fifo->Push( fMpeg4Buffer ) ) - { - fMpeg4Buffer = NULL; - } - else - { - Unlock(); - return false; - } - } - - if( ( fResizedBuffer = fTitle->fResizedFifo->Pop() ) ) - { - if( fResizedBuffer->fPass != fPass ) - { - fPass = fResizedBuffer->fPass; - Init(); - } - - fManager->SetPosition( fResizedBuffer->fPosition ); - EncodeBuffer(); - } - else - { - Unlock(); - return false; - } - - Unlock(); - return true; -} - -bool HBMpeg4Encoder::Lock() -{ - fLock->Lock(); - if( fUsed ) - { - fLock->Unlock(); - return false; - } - 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( HB_ERROR_MPEG4_INIT ); - return; - } - - fContext = avcodec_alloc_context(); - fContext->bit_rate = 1024 * fTitle->fBitrate; - fContext->bit_rate_tolerance = 10240 * fTitle->fBitrate; - fContext->width = fTitle->fOutWidth; - fContext->height = fTitle->fOutHeight; - fContext->frame_rate = fTitle->fRate; - fContext->frame_rate_base = fTitle->fScale; - fContext->gop_size = 10 * fTitle->fRate / fTitle->fScale; - - if( fPass == 1 ) - { - fContext->flags |= CODEC_FLAG_PASS1; - - char fileName[1024]; memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", fManager->GetPid() ); - fFile = fopen( fileName, "w" ); - } - else if( fPass == 2 ) - { - fContext->flags |= CODEC_FLAG_PASS2; - - char fileName[1024]; memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.ffmpeg.log", fManager->GetPid() ); - fFile = fopen( fileName, "r" ); - fseek( fFile, 0, SEEK_END ); - uint32_t size = ftell( fFile ); - fLog = (char*) malloc( size + 1 ); - fseek( fFile, 0, SEEK_SET ); - fread( fLog, size, 1, fFile ); - fclose( fFile ); - fLog[size] = '\0'; - fContext->stats_in = fLog; - } - - if( avcodec_open( fContext, codec ) < 0 ) - { - Log( "HBMpeg4Encoder: avcodec_open() failed" ); - fManager->Error( HB_ERROR_MPEG4_INIT ); - return; - } -} - -void HBMpeg4Encoder::EncodeBuffer() -{ - fFrame->data[0] = fResizedBuffer->fData; - fFrame->data[1] = fFrame->data[0] + fTitle->fOutWidth * - fTitle->fOutHeight; - fFrame->data[2] = fFrame->data[1] + fTitle->fOutWidth * - fTitle->fOutHeight / 4; - fFrame->linesize[0] = fTitle->fOutWidth; - fFrame->linesize[1] = fTitle->fOutWidth / 2; - fFrame->linesize[2] = fTitle->fOutWidth / 2; - - fMpeg4Buffer = new HBBuffer( 3 * fTitle->fOutWidth * - fTitle->fOutHeight / 2 ); - /* Should be really too much... */ - - fMpeg4Buffer->fPosition = fResizedBuffer->fPosition; - fMpeg4Buffer->fSize = - avcodec_encode_video( fContext, fMpeg4Buffer->fData, - fMpeg4Buffer->fAllocSize, fFrame ); - fMpeg4Buffer->fKeyFrame = ( fContext->coded_frame->key_frame != 0 ); - - if( fResizedBuffer->fPass == 1 ) - { - if( fContext->stats_out ) - { - fprintf( fFile, "%s", fContext->stats_out ); - } - delete fMpeg4Buffer; - fMpeg4Buffer = NULL; - } - - delete fResizedBuffer; - fResizedBuffer = NULL; -} - diff --git a/core/Mpeg4Encoder.h b/core/Mpeg4Encoder.h deleted file mode 100644 index 3d20f315a..000000000 --- a/core/Mpeg4Encoder.h +++ /dev/null @@ -1,41 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MPEG4_ENCODER_H -#define HB_MPEG4_ENCODER_H - -#include "Common.h" - -class HBMpeg4Encoder -{ - public: - HBMpeg4Encoder( HBManager * manager, - HBTitle * title ); - bool Work(); - - private: - bool Lock(); - void Unlock(); - - void Init(); - 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 deleted file mode 100644 index 249ee2738..000000000 --- a/core/MpegDemux.cpp +++ /dev/null @@ -1,308 +0,0 @@ -/* $Id: MpegDemux.cpp,v 1.20 2003/10/16 13:36:17 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#include "MpegDemux.h" -#include "Manager.h" -#include "Fifo.h" - -extern "C" { -#include <a52dec/a52.h> -} - -HBMpegDemux::HBMpegDemux( HBManager * manager, HBTitle * title, - HBAudio * audio1, HBAudio * audio2 ) -{ - fManager = manager; - fTitle = title; - fAudio1 = audio1; - fAudio2 = audio2; - - fLock = new HBLock(); - fUsed = false; - - fPSBuffer = NULL; - fESBuffer = NULL; - fESBufferList = NULL; - - fFirstVideoPTS = -1; - fFirstAudio1PTS = -1; - fFirstAudio2PTS = -1; -} - -HBMpegDemux::~HBMpegDemux() -{ - /* Free memory */ - if( fESBufferList ) - { - while( ( fESBuffer = (HBBuffer*) fESBufferList->ItemAt( 0 ) ) ) - { - fESBufferList->RemoveItem( fESBuffer ); - delete fESBuffer; - } - } - delete fLock; -} - -bool HBMpegDemux::Work() -{ - if( !Lock() ) - { - return false; - } - - /* Push waiting buffers */ - if( fESBufferList ) - { - for( uint32_t i = 0; i < fESBufferList->CountItems(); ) - { - 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 ) - { - fFirstVideoPTS = fESBuffer->fPTS; - Log( "HBMpegDemux: got first 0xE0 packet (%lld)", - fFirstVideoPTS ); - } - if( fTitle->fMpeg2Fifo->Push( fESBuffer ) ) - { - fESBufferList->RemoveItem( fESBuffer ); - } - else - { - i++; - } - } - else if( fAudio1 && - fESBuffer->fStreamId == fAudio1->fId ) - { - if( fFirstAudio1PTS < 0 ) - { - fFirstAudio1PTS = fESBuffer->fPTS; - Log( "HBMpegDemux: got first 0x%x packet (%lld)", - fAudio1->fId, fFirstAudio1PTS ); - - fAudio1->fDelay = - ( fFirstAudio1PTS - fFirstVideoPTS ) / 90; - } - if( fAudio1->fAc3Fifo->Push( fESBuffer ) ) - { - fESBufferList->RemoveItem( fESBuffer ); - } - else - { - i++; - } - } - else if( fAudio2 && - fESBuffer->fStreamId == fAudio2->fId ) - { - if( fFirstAudio2PTS < 0 ) - { - fFirstAudio2PTS = fESBuffer->fPTS; - Log( "HBMpegDemux: got first 0x%x packet (%lld)", - fAudio2->fId, fFirstAudio2PTS ); - - fAudio2->fDelay = - ( fFirstAudio2PTS - fFirstVideoPTS ) / 90; - } - if( fAudio2->fAc3Fifo->Push( fESBuffer ) ) - { - fESBufferList->RemoveItem( fESBuffer ); - } - else - { - i++; - } - } - else - { - fESBufferList->RemoveItem( fESBuffer ); - delete fESBuffer; - } - } - - if( !fESBufferList->CountItems() ) - { - delete fESBufferList; - fESBufferList = NULL; - } - else - { - Unlock(); - return false; - } - } - - /* Get a PS packet */ - if( ( fPSBuffer = fTitle->fPSFifo->Pop() ) ) - { - /* Get the ES data in it */ - PStoES( fPSBuffer, &fESBufferList ); - } - else - { - Unlock(); - return false; - } - - Unlock(); - return true; -} - -bool HBMpegDemux::Lock() -{ - fLock->Lock(); - if( fUsed ) - { - 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 ) -{ -#define psData (psBuffer->fData) - - uint32_t pos = 0; - - /* pack_header */ - if( psData[pos] != 0 || psData[pos+1] != 0 || - psData[pos+2] != 0x1 || psData[pos+3] != 0xBA ) - { - Log( "PStoES: not a PS packet (%02x%02x%02x%02x)", - psData[pos] << 24, psData[pos+1] << 16, - psData[pos+2] << 8, psData[pos+3] ); - delete psBuffer; - (*_esBufferList) = NULL; - return false; - } - pos += 4; /* pack_start_code */ - pos += 9; /* pack_header */ - pos += 1 + ( psData[pos] & 0x7 ); /* stuffing bytes */ - - /* system_header */ - if( psData[pos] == 0 && psData[pos+1] == 0 && - psData[pos+2] == 0x1 && psData[pos+3] == 0xBB ) - { - uint32_t header_length; - - pos += 4; /* system_header_start_code */ - header_length = ( psData[pos] << 8 ) + psData[pos+1]; - pos += 2 + header_length; - } - - HBList * esBufferList = new HBList(); - HBBuffer * esBuffer; - - /* PES */ - while( pos + 6 < psBuffer->fSize && - psData[pos] == 0 && psData[pos+1] == 0 && psData[pos+2] == 0x1 ) - { - uint32_t streamId; - uint32_t PES_packet_length; - uint32_t PES_packet_end; - uint32_t PES_header_data_length; - uint32_t PES_header_end; - bool hasPTS; - uint64_t PTS = 0; - - pos += 3; /* packet_start_code_prefix */ - streamId = psData[pos]; - pos += 1; - - PES_packet_length = ( psData[pos] << 8 ) + psData[pos+1]; - pos += 2; /* PES_packet_length */ - PES_packet_end = pos + PES_packet_length; - - if( streamId != 0xE0 && streamId != 0xBD ) - { - /* Not interesting */ - pos = PES_packet_end; - continue; - } - - hasPTS = ( ( psData[pos+1] >> 6 ) & 0x2 ); - pos += 2; /* Required headers */ - - PES_header_data_length = psData[pos]; - pos += 1; - PES_header_end = pos + PES_header_data_length; - - if( hasPTS ) - { - PTS = ( ( ( (uint64_t) psData[pos] >> 1 ) & 0x7 ) << 30 ) + - ( psData[pos+1] << 22 ) + - ( ( psData[pos+2] >> 1 ) << 15 ) + - ( psData[pos+3] << 7 ) + - ( psData[pos+4] >> 1 ); - } - - pos = PES_header_end; - - if( streamId == 0xBD ) - { - /* A52: don't ask */ - streamId |= ( psData[pos] << 8 ); - pos += 4; - } - - /* Sanity check */ - if( pos >= PES_packet_end ) - { - Log( "PStoES: pos >= PES_packet_end" ); - pos = PES_packet_end; - continue; - } - - /* Here we hit we ES payload */ - esBuffer = new HBBuffer( PES_packet_end - pos ); - - esBuffer->fPosition = psBuffer->fPosition; - esBuffer->fPass = psBuffer->fPass; - esBuffer->fStreamId = streamId; - esBuffer->fPTS = PTS; - memcpy( esBuffer->fData, psBuffer->fData + pos, - PES_packet_end - pos ); - - esBufferList->AddItem( esBuffer ); - - pos = PES_packet_end; - } - - delete psBuffer; - - if( !esBufferList->CountItems() ) - { - delete esBufferList; - esBufferList = NULL; - } - - (*_esBufferList) = esBufferList; - return true; - -#undef psData -} diff --git a/core/MpegDemux.h b/core/MpegDemux.h deleted file mode 100644 index 187a08de9..000000000 --- a/core/MpegDemux.h +++ /dev/null @@ -1,43 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_MPEG_DEMUX_H -#define HB_MPEG_DEMUX_H - -#include "Common.h" - -bool PStoES( HBBuffer * psBuffer, HBList ** _esBufferList ); - -class HBMpegDemux -{ - public: - HBMpegDemux( HBManager * manager, HBTitle * title, - HBAudio * audio1, HBAudio * audio2 ); - ~HBMpegDemux(); - bool Work(); - - private: - bool Lock(); - void Unlock(); - - HBManager * fManager; - HBTitle * fTitle; - HBAudio * fAudio1; - HBAudio * fAudio2; - - HBLock * fLock; - bool fUsed; - - HBBuffer * fPSBuffer; - HBBuffer * fESBuffer; - HBList * fESBufferList; - - int64_t fFirstVideoPTS; - int64_t fFirstAudio1PTS; - int64_t fFirstAudio2PTS; -}; - -#endif diff --git a/core/Resizer.cpp b/core/Resizer.cpp deleted file mode 100644 index c49a39bf3..000000000 --- a/core/Resizer.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* $Id: Resizer.cpp,v 1.9 2003/10/14 14:35:20 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#include "Resizer.h" -#include "Manager.h" -#include "Fifo.h" - -#include <ffmpeg/avcodec.h> - -HBResizer::HBResizer( HBManager * manager, HBTitle * title ) -{ - fManager = manager; - fTitle = title; - - /* Lock */ - fLock = new HBLock(); - fUsed = false; - - /* Init libavcodec */ - fResampleContext = - img_resample_full_init( fTitle->fOutWidth, fTitle->fOutHeight, - fTitle->fInWidth, fTitle->fInHeight, - fTitle->fTopCrop, fTitle->fBottomCrop, - fTitle->fLeftCrop, fTitle->fRightCrop ); - - /* Buffers & pictures */ - 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; - } - - /* Push the latest resized buffer */ - if( fResizedBuffer ) - { - if( fTitle->fResizedFifo->Push( fResizedBuffer ) ) - { - fResizedBuffer = NULL; - } - else - { - Unlock(); - return false; - } - } - - /* Get a new raw picture */ - if( ( fRawBuffer = fTitle->fRawFifo->Pop() ) ) - { - /* Do the job */ - avpicture_fill( fRawPicture, fRawBuffer->fData, - PIX_FMT_YUV420P, fTitle->fInWidth, - fTitle->fInHeight ); - - fResizedBuffer = new HBBuffer( 3 * fTitle->fOutWidth * - fTitle->fOutHeight / 2 ); - 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( fDeinterlacedPicture, fRawPicture, - PIX_FMT_YUV420P, - fTitle->fInWidth, - fTitle->fInHeight ); - img_resample( fResampleContext, fResizedPicture, - fDeinterlacedPicture ); - } - else - { - img_resample( fResampleContext, fResizedPicture, - fRawPicture ); - } - delete fRawBuffer; - fRawBuffer = NULL; - } - else - { - Unlock(); - return false; - } - - Unlock(); - return true; -} - -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 deleted file mode 100644 index f6d4a4568..000000000 --- a/core/Resizer.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_RESIZER_H -#define HB_RESIZER_H - -#include "Common.h" - -class HBResizer -{ - public: - HBResizer( HBManager * manager, HBTitle * title ); - ~HBResizer(); - bool Work(); - - private: - 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/Scale.c b/core/Scale.c new file mode 100644 index 000000000..7e9295962 --- /dev/null +++ b/core/Scale.c @@ -0,0 +1,139 @@ +/* $Id: Scale.c,v 1.4 2003/11/06 13:03:19 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Fifo.h" +#include "Scale.h" +#include "Work.h" + +#include <ffmpeg/avcodec.h> + +/* Local prototypes */ +static int ScaleWork( HBWork * ); + +struct HBScale +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBTitle * title; + + ImgReSampleContext * context; + AVPicture rawPicture; + HBBuffer * deintBuffer; + AVPicture deintPicture; + HBBuffer * scaledBuffer; + AVPicture scaledPicture; +}; + +HBScale * HBScaleInit( HBHandle * handle, HBTitle * title ) +{ + HBScale * s; + if( !( s = malloc( sizeof( HBScale ) ) ) ) + { + HBLog( "HBScaleInit: malloc() failed, gonna crash" ); + return NULL; + } + + s->name = strdup( "Scale" ); + s->work = ScaleWork; + + s->handle = handle; + s->title = title; + + /* Init libavcodec */ + s->context = + img_resample_full_init( title->outWidth, title->outHeight, + title->inWidth, title->inHeight, + title->topCrop, title->bottomCrop, + title->leftCrop, title->rightCrop ); + + /* Allocate a constant buffer used for deinterlacing */ + s->deintBuffer = HBBufferInit( 3 * title->inWidth * + title->inHeight / 2 ); + avpicture_fill( &s->deintPicture, s->deintBuffer->data, + PIX_FMT_YUV420P, title->inWidth, title->inHeight ); + + s->scaledBuffer = NULL; + + return s; +} + +void HBScaleClose( HBScale ** _s ) +{ + HBScale * s = *_s; + + img_resample_close( s->context ); + HBBufferClose( &s->deintBuffer ); + free( s->name ); + free( s ); + + *_s = NULL; +} + +static int ScaleWork( HBWork * w ) +{ + HBScale * s = (HBScale*) w; + HBTitle * title = s->title; + HBBuffer * rawBuffer; + + int didSomething = 0; + + /* Push scaled buffer */ + if( s->scaledBuffer ) + { + if( HBFifoPush( title->scaledFifo, &s->scaledBuffer ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + } + + /* Get a new raw picture */ + if( ( rawBuffer = HBFifoPop( title->rawFifo ) ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + /* Allocate new buffer for the scaled picture */ + s->scaledBuffer = HBBufferInit( 3 * title->outWidth * + title->outHeight / 2 ); + s->scaledBuffer->position = rawBuffer->position; + s->scaledBuffer->pass = rawBuffer->pass; + + /* libavcodec stuff */ + avpicture_fill( &s->rawPicture, rawBuffer->data, PIX_FMT_YUV420P, + title->inWidth, title->inHeight ); + avpicture_fill( &s->scaledPicture, s->scaledBuffer->data, + PIX_FMT_YUV420P, title->outWidth, + title->outHeight ); + + /* Do the job */ + if( title->deinterlace ) + { + avpicture_deinterlace( &s->deintPicture, &s->rawPicture, + PIX_FMT_YUV420P, title->inWidth, + title->inHeight ); + img_resample( s->context, &s->scaledPicture, + &s->deintPicture ); + } + else + { + img_resample( s->context, &s->scaledPicture, &s->rawPicture ); + } + + /* Free memory */ + HBBufferClose( &rawBuffer ); + + return didSomething; +} + diff --git a/core/Scale.h b/core/Scale.h new file mode 100644 index 000000000..cf06ad661 --- /dev/null +++ b/core/Scale.h @@ -0,0 +1,15 @@ +/* $Id: Scale.h,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_SCALE_H +#define HB_SCALE_H + +#include "HandBrakeInternal.h" + +HBScale * HBScaleInit( HBHandle *, HBTitle * ); +void HBScaleClose( HBScale ** ); + +#endif diff --git a/core/Scan.c b/core/Scan.c new file mode 100644 index 000000000..83f2fc098 --- /dev/null +++ b/core/Scan.c @@ -0,0 +1,395 @@ +/* $Id: Scan.c,v 1.4 2003/11/06 13:03:19 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Fifo.h" +#include "Languages.h" +#include "Scan.h" +#include "Thread.h" + +#include <dvdread/ifo_types.h> +#include <dvdplay/dvdplay.h> +#include <dvdplay/info.h> +#include <dvdplay/state.h> +#include <dvdplay/nav.h> + +#include <mpeg2dec/mpeg2.h> + +/* Local prototypes */ +static void ScanThread( void * ); +static HBTitle * ScanTitle( HBScan *, dvdplay_ptr vmg, int index ); +static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, + HBTitle * title, int which ); +static char * LanguageForCode( int code ); + +struct HBScan +{ + HBHandle * handle; + char * device; + int title; + int die; + HBThread * thread; +}; + +HBScan * HBScanInit( HBHandle * handle, char * device, int title ) +{ + HBScan * s; + if( !( s = malloc( sizeof( HBScan ) ) ) ) + { + HBLog( "HBScanInit: malloc() failed, gonna crash" ); + return NULL; + } + + s->handle = handle; + s->device = strdup( device ); + s->title = title; + s->die = 0; + s->thread = HBThreadInit( "scan", ScanThread, s, + HB_NORMAL_PRIORITY ); + + return s; +} + +void HBScanClose( HBScan ** _s ) +{ + HBScan * s = *_s; + + s->die = 1; + HBThreadClose( &s->thread ); + + free( s->device ); + free( s ); + *_s = NULL; +} + +static void ScanThread( void * _s ) +{ + HBScan * s = (HBScan*) _s; + dvdplay_ptr vmg; + HBList * titleList = HBListInit(); + HBTitle * title; + int i; + + HBLog( "HBScan: opening device %s", s->device ); + HBScanning( s->handle, 0 ); + + vmg = dvdplay_open( s->device, NULL, NULL ); + if( !vmg ) + { + HBLog( "HBScan: dvdplay_open() failed (%s)", s->device ); + HBScanDone( s->handle, titleList ); + return; + } + + /* Detect titles */ + for( i = ( s->title ? s->title - 1 : 0 ); + i < ( s->title ? s->title : dvdplay_title_nr( vmg ) ); + i++ ) + { + if( s->die ) + { + break; + } + + if( !( title = ScanTitle( s, vmg, i + 1 ) ) ) + { + continue; + } + + HBListAdd( titleList, title ); + } + + HBLog( "HBScan: closing device %s", s->device ); + dvdplay_close( vmg ); + + HBScanDone( s->handle, titleList ); +} + +static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) +{ + HBTitle * title; + int audio_nr, foo; + audio_attr_t * attr; + HBAudio * audio; + int i; + uint8_t dummy[DVD_VIDEO_LB_LEN]; + + HBLog( "HBScan: scanning title %d", index ); + HBScanning( s->handle, index ); + + title = HBTitleInit( s->device, index ); + dvdplay_start( vmg, index ); + + /* Length */ + title->length = dvdplay_title_time( vmg ); + HBLog( "HBScan: title length is %d seconds", title->length ); + + /* Discard titles under 10 seconds */ + if( title->length < 10 ) + { + HBLog( "HBScan: ignoring title %d (too short)", index ); + HBTitleClose( &title ); + return NULL; + } + + /* Detect languages */ + dvdplay_audio_info( vmg, &audio_nr, &foo ); + + for( i = 0; i < audio_nr; i++ ) + { + int id; + int j; + + if( s->die ) + { + break; + } + + id = dvdplay_audio_id( vmg, i ); + + if( id < 1 ) + { + continue; + } + + if( ( id & 0xFF ) != 0xBD ) + { + HBLog( "HBScan: non-AC3 audio track detected, ignoring" ); + continue; + } + + /* Check if we don't already found an track with the same id */ + audio = NULL; + for( j = 0; j < HBListCountItems( title->audioList ); j++ ) + { + audio = (HBAudio*) HBListItemAt( title->audioList, j ); + if( id == audio->id ) + { + break; + } + else + { + audio = NULL; + } + } + + if( audio ) + { + HBLog( "HBScan: discarding duplicate track %x", id ); + continue; + } + + attr = dvdplay_audio_attr( vmg, j ); + audio = HBAudioInit( id, LanguageForCode( attr->lang_code ) ); + HBLog( "HBScan: new language (%x, %s)", id, audio->language ); + HBListAdd( title->audioList, audio ); + } + + /* Discard titles with no audio tracks */ + if( !HBListCountItems( title->audioList ) ) + { + HBLog( "HBScan: ignoring title %d (no audio track)", index ); + HBTitleClose( &title ); + return NULL; + } + + /* Kludge : libdvdplay wants we to read a first block before seeking */ + dvdplay_read( vmg, dummy, 1 ); + + + for( i = 0; i < 10; i++ ) + { + if( s->die ) + { + break; + } + + if( !DecodeFrame( s, vmg, title, i ) ) + { + HBLog( "HBScan: ignoring title %d (could not decode)", + index ); + HBTitleClose( &title ); + return NULL; + } + } + + if( title->inHeight * title->aspect > + title->inWidth * VOUT_ASPECT_FACTOR ) + { + title->outWidthMax = title->inWidth; + title->outHeightMax = MULTIPLE_16( (uint64_t)title->inWidth * + VOUT_ASPECT_FACTOR / title->aspect ); + } + else + { + title->outWidthMax = MULTIPLE_16( (uint64_t)title->inHeight * + title->aspect / VOUT_ASPECT_FACTOR ); + title->outHeightMax = title->inHeight; + } + + /* Default picture size */ + title->outWidth = title->outWidthMax; + title->outHeight = title->outHeightMax; + + return title; +} + +static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, + HBTitle * title, int which ) +{ + int titleFirst = dvdplay_title_first( vmg ); + int titleEnd = dvdplay_title_end( vmg ); + int pictureStart = ( which + 1 ) * ( titleEnd - titleFirst ) / 11; + int pictureEnd = titleFirst + ( which + 2 ) * + ( titleEnd - titleFirst ) / 11; + + mpeg2dec_t * handle; + const mpeg2_info_t * info; + mpeg2_state_t state; + char fileName[1024]; + FILE * file; + + HBList * esBufferList = HBListInit(); + HBBuffer * psBuffer = NULL; + HBBuffer * esBuffer = NULL; + + /* Seek to the right place */ + dvdplay_seek( vmg, pictureStart ); + + /* Init libmpeg2 */ + handle = mpeg2_init(); + info = mpeg2_info( handle ); + + /* Init the destination file */ + memset( fileName, 0, 1024 ); + sprintf( fileName, "/tmp/HB.%d.%d.%d", HBGetPid( s->handle ), + title->index, which ); + file = fopen( fileName, "w" ); + +#define CLEANUP \ + while( ( esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 ) ) ) \ + { \ + HBListRemove( esBufferList, esBuffer ); \ + HBBufferClose( &esBuffer ); \ + } \ + HBListClose( &esBufferList ); \ + if( psBuffer ) HBBufferClose( &psBuffer ); \ + if( esBuffer ) HBBufferClose( &esBuffer ); \ + mpeg2_close( handle ); \ + fclose( file ) + + for( ;; ) + { + state = mpeg2_parse( handle ); + + if( state == STATE_BUFFER ) + { + /* Free the previous buffer */ + if( esBuffer ) + { + HBBufferClose( &esBuffer ); + } + + /* Get a new one */ + while( !esBuffer ) + { + while( !HBListCountItems( esBufferList ) ) + { + psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN ); + if( dvdplay_read( vmg, psBuffer->data, 1 ) != 1 || + !HBPStoES( &psBuffer, esBufferList ) ) + { + HBLog( "HBScan: failed to get a valid PS " + "packet" ); + CLEANUP; + return 0; + } + + if( dvdplay_position( vmg ) >= pictureEnd ) + { + HBLog( "HBScan: gone too far, aborting" ); + CLEANUP; + return 0; + } + } + + esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 ); + HBListRemove( esBufferList, esBuffer ); + + if( esBuffer->streamId != 0xE0 ) + { + HBBufferClose( &esBuffer ); + } + } + + /* Feed libmpeg2 */ + mpeg2_buffer( handle, esBuffer->data, + esBuffer->data + esBuffer->size ); + } + else if( state == STATE_SEQUENCE ) + { + /* Get size & framerate info */ + title->inWidth = info->sequence->width; + title->inHeight = info->sequence->height; + title->aspect = (uint64_t)info->sequence->display_width * + info->sequence->pixel_width * VOUT_ASPECT_FACTOR / + ( info->sequence->display_height * + info->sequence->pixel_height ); + title->rate = 27000000; + title->rateBase = info->sequence->frame_period; + } + else if( ( state == STATE_SLICE || state == STATE_END ) && + ( info->display_fbuf ) && + ( info->display_picture->flags & PIC_MASK_CODING_TYPE ) + == PIC_FLAG_CODING_TYPE_I ) + { + /* Write the raw picture to a file */ + fwrite( info->display_fbuf->buf[0], + title->inWidth * title->inHeight, 1, file ); + fwrite( info->display_fbuf->buf[1], + title->inWidth * title->inHeight / 4, 1, file ); + fwrite( info->display_fbuf->buf[2], + title->inWidth * title->inHeight / 4, 1, file ); + break; + } + else if( state == STATE_INVALID ) + { + /* Reset libmpeg2 */ + mpeg2_close( handle ); + handle = mpeg2_init(); + } + } + + CLEANUP; + + return 1; + +#undef CLEANUP +} + +static char * LanguageForCode( int code ) +{ + char codeString[2]; + iso639_lang_t * lang; + + codeString[0] = ( code >> 8 ) & 0xFF; + codeString[1] = code & 0xFF; + + for( lang = languages; lang->engName; lang++ ) + { + if( !strncmp( lang->iso639_1, codeString, 2 ) ) + { + if( *lang->nativeName ) + { + return lang->nativeName; + } + + return lang->engName; + } + } + + return "Unknown"; +} + diff --git a/core/Scan.h b/core/Scan.h new file mode 100644 index 000000000..5cc8542e7 --- /dev/null +++ b/core/Scan.h @@ -0,0 +1,15 @@ +/* $Id: Scan.h,v 1.2 2003/11/06 13:03:19 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_SCAN_H +#define HB_SCAN_H + +#include "HandBrakeInternal.h" + +HBScan * HBScanInit( HBHandle *, char * device, int title ); +void HBScanClose( HBScan ** ); + +#endif diff --git a/core/Scanner.cpp b/core/Scanner.cpp deleted file mode 100644 index 44ff6be3a..000000000 --- a/core/Scanner.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#include "Scanner.h" -#include "Manager.h" -#include "Fifo.h" -#include "MpegDemux.h" - -#include <dvdread/ifo_types.h> -#include <dvdplay/dvdplay.h> -#include <dvdplay/info.h> -#include <dvdplay/state.h> -#include <dvdplay/nav.h> - -extern "C" { -#include <mpeg2dec/mpeg2.h> -} - -HBScanner::HBScanner( HBManager * manager, char * device ) - : HBThread( "scanner", HB_NORMAL_PRIORITY ) -{ - fManager = manager; - fDevice = strdup( device ); - - Run(); -} - -void HBScanner::DoWork() -{ - Log( "HBScanner: opening device %s", fDevice ); - - dvdplay_ptr vmg; - vmg = dvdplay_open( fDevice, NULL, NULL ); - if( !vmg ) - { - Log( "HBScanner: dvdplay_open() failed (%s)", - fDevice ); - fManager->ScanDone( NULL ); - return; - } - - /* Detect titles */ - HBList * titleList = new HBList(); - HBTitle * title; - for( int i = 0; i < dvdplay_title_nr( vmg ); i++ ) - { - if( fDie ) - { - break; - } - - Log( "HBScanner: scanning title %d", i + 1 ); - fManager->Scanning( fDevice, i + 1 ); - - title = new HBTitle( fDevice, i + 1 ); - - if( ScanTitle( title, vmg ) ) - { - titleList->AddItem( title ); - } - else - { - Log( "HBScanner: ignoring title %d", i + 1 ); - delete title; - } - } - - Log( "HBScanner: closing device %s", fDevice ); - dvdplay_close( vmg ); - - fManager->ScanDone( titleList ); -} - -bool HBScanner::ScanTitle( HBTitle * title, dvdplay_ptr vmg ) -{ - dvdplay_start( vmg, title->fIndex ); - - /* Length */ - title->fLength = dvdplay_title_time( vmg ); - Log( "HBScanner::ScanTitle: title length is %lld seconds", - title->fLength ); - - /* Discard titles under 10 seconds */ - if( title->fLength < 10 ) - { - return false; - } - - /* Detect languages */ - int audio_nr, foo; - dvdplay_audio_info( vmg, &audio_nr, &foo ); - - audio_attr_t * attr; - HBAudio * audio; - for( int i = 0; i < audio_nr; i++ ) - { - if( fDie ) - { - break; - } - - int id = dvdplay_audio_id( vmg, i ); - - if( id < 1 ) - { - 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 - { - audio = NULL; - } - } - - 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 */ - if( !title->fAudioList->CountItems() ) - { - return false; - } - - /* Kludge : libdvdplay wants we to read a first block before seeking */ - uint8_t dummyBuf[DVD_VIDEO_LB_LEN]; - dvdplay_read( vmg, dummyBuf, 1 ); - - for( int i = 0; i < 10; i++ ) - { - if( fDie ) - { - break; - } - - if( !DecodeFrame( title, vmg, i ) ) - { - return false; - } - } - - if( title->fInHeight * title->fAspect > - title->fInWidth * VOUT_ASPECT_FACTOR ) - { - title->fOutWidthMax = title->fInWidth; - title->fOutHeightMax = MULTIPLE_16( (uint64_t)title->fInWidth * - VOUT_ASPECT_FACTOR / title->fAspect ); - } - else - { - title->fOutWidthMax = MULTIPLE_16( (uint64_t)title->fInHeight * - title->fAspect / VOUT_ASPECT_FACTOR ); - title->fOutHeightMax = title->fInHeight; - } - - /* Default picture size */ - title->fOutWidth = title->fOutWidthMax; - title->fOutHeight = title->fOutHeightMax; - - return true; -} -bool HBScanner::DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i ) -{ - /* Seek to the right place */ - int titleFirst = dvdplay_title_first ( vmg ); - int titleEnd = dvdplay_title_end( vmg ); - - dvdplay_seek( vmg, ( i + 1 ) * ( titleEnd - titleFirst ) / 11 ) ; - - /* Init libmpeg2 */ - mpeg2dec_t * handle = mpeg2_init(); - const mpeg2_info_t * info = mpeg2_info( handle ); - mpeg2_state_t state; - - /* Init the destination file */ - char fileName[1024]; - memset( fileName, 0, 1024 ); - sprintf( fileName, "/tmp/HB.%d.%x.%d", fManager->GetPid(), - (uint32_t) title, i ); - FILE * file = fopen( fileName, "w" ); - - HBList * esBufferList = NULL; - HBBuffer * psBuffer = NULL; - HBBuffer * esBuffer = NULL; - - for( ;; ) - { - state = mpeg2_parse( handle ); - - if( state == STATE_BUFFER ) - { - /* Free the previous buffer */ - if( esBuffer ) - { - delete esBuffer; - esBuffer = NULL; - } - - /* Get a new one */ - while( !esBuffer ) - { - while( !esBufferList ) - { - psBuffer = new HBBuffer( DVD_VIDEO_LB_LEN ); - if( dvdplay_read( vmg, psBuffer->fData, 1 ) != 1 || - !PStoES( psBuffer, &esBufferList ) ) - { - Log( "HBScanner::DecodeFrame: failed to get " - "a valid PS packet" ); - mpeg2_close( handle ); - fclose( file ); - return false; - } - } - - esBuffer = (HBBuffer*) esBufferList->ItemAt( 0 ); - esBufferList->RemoveItem( esBuffer ); - if( !esBufferList->CountItems() ) - { - delete esBufferList; - esBufferList = NULL; - } - - if( esBuffer->fStreamId != 0xE0 ) - { - delete esBuffer; - esBuffer = NULL; - } - } - - /* Feed libmpeg2 */ - mpeg2_buffer( handle, esBuffer->fData, - esBuffer->fData + esBuffer->fSize ); - } - else if( state == STATE_SEQUENCE ) - { - /* Get size & framerate info */ - title->fInWidth = info->sequence->width; - title->fInHeight = info->sequence->height; - title->fAspect = (uint64_t)info->sequence->display_width * - info->sequence->pixel_width * VOUT_ASPECT_FACTOR / - ( info->sequence->display_height * - info->sequence->pixel_height ); - title->fRate = 27000000; - title->fScale = info->sequence->frame_period; - } - else if( ( state == STATE_SLICE || state == STATE_END ) && - ( info->display_fbuf ) && - ( info->display_picture->flags & PIC_MASK_CODING_TYPE ) - == PIC_FLAG_CODING_TYPE_I ) - { - /* Write the raw picture to a file */ - fwrite( info->display_fbuf->buf[0], - title->fInWidth * title->fInHeight, 1, file ); - fwrite( info->display_fbuf->buf[1], - title->fInWidth * title->fInHeight / 4, 1, file ); - fwrite( info->display_fbuf->buf[2], - title->fInWidth * title->fInHeight / 4, 1, file ); - break; - } - else if( state == STATE_INVALID ) - { - /* Reset libmpeg2 */ - mpeg2_close( handle ); - handle = mpeg2_init(); - } - } - - mpeg2_close( handle ); - - fclose( file ); - - return true; -} diff --git a/core/Scanner.h b/core/Scanner.h deleted file mode 100644 index dbdb587c4..000000000 --- a/core/Scanner.h +++ /dev/null @@ -1,27 +0,0 @@ -/* $Id: Scanner.h,v 1.5 2003/09/30 21:21:32 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_SCANNER_H -#define HB_SCANNER_H - -#include "Common.h" -#include "Thread.h" - -class HBScanner : public HBThread -{ - public: - HBScanner( HBManager * manager, char * device ); - - private: - void DoWork(); - bool ScanTitle( HBTitle * title, dvdplay_ptr vmg ); - bool DecodeFrame( HBTitle * title, dvdplay_ptr vmg, int i ); - - HBManager * fManager; - char * fDevice; -}; - -#endif diff --git a/core/Thread.c b/core/Thread.c new file mode 100644 index 000000000..77caa0ee5 --- /dev/null +++ b/core/Thread.c @@ -0,0 +1,138 @@ +/* $Id: Thread.c,v 1.4 2003/11/06 15:51:36 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Thread.h" + +struct HBThread +{ + char * name; + int priority; + void (*function) ( void * ); + void * arg; + +#if defined( SYS_BEOS ) + int thread; +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_t thread; +#elif defined( SYS_CYGWIN ) + /* TODO */ + int thread; +#endif +}; + +#ifndef SYS_CYGWIN +static void ThreadFunc( void * t ); +#endif + +HBThread * HBThreadInit( char * name, void (* function)(void *), + void * arg, int priority ) +{ + HBThread * t; + if( !( t = malloc( sizeof( HBThread ) ) ) ) + { + HBLog( "HBThreadInit: malloc() failed, gonna crash" ); + return NULL; + } + + t->name = strdup( name ); + t->priority = priority; + t->function = function; + t->arg = arg; + +#if defined( SYS_BEOS ) + t->thread = spawn_thread( (int32 (*)( void * )) ThreadFunc, + name, priority, t ); + resume_thread( t->thread ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_create( &t->thread, NULL, + (void * (*)( void * )) ThreadFunc, t ); +#elif defined( SYS_CYGWIN ) + /* TODO */ + t->thread = 0; +#endif + + HBLog( "HBThreadInit: thread %d started (\"%s\")", + t->thread, t->name ); + + return t; +} + +#ifndef SYS_CYGWIN +static void ThreadFunc( void * _t ) +{ + HBThread * t = (HBThread*) _t; + +#if defined( SYS_MACOSX ) + struct sched_param param; + memset( ¶m, 0, sizeof( struct sched_param ) ); + param.sched_priority = t->priority; + if( pthread_setschedparam( pthread_self(), SCHED_OTHER, ¶m ) ) + { + HBLog( "HBThreadInit: couldn't set thread priority" ); + } +#endif + + t->function( t->arg ); +} +#endif + +void HBThreadClose( HBThread ** _t ) +{ + HBThread * t = *_t; + +#if defined( SYS_BEOS ) + long exitValue; + wait_for_thread( t->thread, &exitValue ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_join( t->thread, NULL ); +#elif defined( SYS_CYGWIN ) + /* TODO */ +#endif + + HBLog( "HBThreadClose: thread %d stopped (\"%s\")", + t->thread, t->name ); + + free( t->name ); + free( t ); + *_t = NULL; +} + +HBLock * HBLockInit() +{ + HBLock * l; + if( !( l = malloc( sizeof( HBLock ) ) ) ) + { + HBLog( "HBLockInit: malloc() failed, gonna crash" ); + return NULL; + } + +#if defined( SYS_BEOS ) + l->sem = create_sem( 1, "sem" ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_init( &l->mutex, NULL ); +#elif defined( SYS_CYGWIN ) + /* TODO */ +#endif + + return l; +} + +void HBLockClose( HBLock ** _l ) +{ + HBLock * l = *_l; + +#if defined( SYS_BEOS ) + delete_sem( l->sem ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_destroy( &l->mutex ); +#elif defined( SYS_CYGWIN ) + /* TODO */ +#endif + free( l ); + + *_l = NULL; +} + diff --git a/core/Thread.cpp b/core/Thread.cpp deleted file mode 100644 index c52f7506a..000000000 --- a/core/Thread.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* $Id: Thread.cpp,v 1.24 2003/10/14 14:35:20 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#if defined( SYS_BEOS ) -# include <OS.h> -# include <Locker.h> -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) -# include <pthread.h> -#endif - -#include "Thread.h" -#include "Fifo.h" - -HBThread::HBThread( char * name, int priority ) -{ - fName = strdup( name ); - fPriority = priority; - fDie = false; - fSuspend = false; -} - -HBThread::~HBThread() -{ - fDie = true; - fSuspend = false; - -#if defined( SYS_BEOS ) - long exit_value; - wait_for_thread( fThread, &exit_value ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_join( fThread, NULL ); -#endif - - Log( "HBThread: thread %d stopped (\"%s\")", fThread, fName ); - free( fName ); -} - -void HBThread::Suspend() -{ - fSuspend = true; -} - -void HBThread::Resume() -{ - fSuspend = false; -} - -int HBThread::GetPid() -{ - return fPid; -} - -void HBThread::Run() -{ -#if defined( SYS_BEOS ) - fThread = spawn_thread( (int32 (*)(void *)) ThreadFunc, - fName, fPriority, this ); - resume_thread( fThread ); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_create( &fThread, NULL, - (void * (*)(void *)) ThreadFunc, this ); -#endif - - Log( "HBThread: thread %d started (\"%s\")", - fThread, fName ); -} - -bool HBThread::Push( HBFifo * fifo, HBBuffer * buffer ) -{ - while( !fDie ) - { - if( fifo->Push( buffer ) ) - { - return true; - } - - Snooze( 10000 ); - } - - delete buffer; - return false; -} - -HBBuffer * HBThread::Pop( HBFifo * fifo ) -{ - HBBuffer * buffer; - - while( !fDie ) - { - if( ( buffer = fifo->Pop() ) ) - { - return buffer; - } - - Snooze( 10000 ); - } - - return NULL; -} - -void HBThread::ThreadFunc( HBThread * _this ) -{ -#if defined( SYS_MACOSX ) - struct sched_param param; - memset( ¶m, 0, sizeof( struct sched_param ) ); - param.sched_priority = _this->fPriority; - if ( pthread_setschedparam( pthread_self(), SCHED_OTHER, ¶m ) ) - { - Log( "HBThread: couldn't set thread priority" ); - } -#endif - - _this->fPid = (int) getpid(); - - _this->DoWork(); -} - -void HBThread::DoWork() -{ -} - - -HBLock::HBLock() -{ -#if defined( SYS_BEOS ) - fLocker = new BLocker(); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_mutex_init( &fMutex, NULL ); -#endif -} - -HBLock::~HBLock() -{ -#if defined( SYS_BEOS ) - delete fLocker; -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_mutex_destroy( &fMutex ); -#endif -} - -void HBLock::Lock() -{ -#if defined( SYS_BEOS ) - fLocker->Lock(); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_mutex_lock( &fMutex ); -#endif -} - -void HBLock::Unlock() -{ -#if defined( SYS_BEOS ) - fLocker->Unlock(); -#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_mutex_unlock( &fMutex ); -#endif -} diff --git a/core/Thread.h b/core/Thread.h index 0a09fabc9..58700aae1 100644 --- a/core/Thread.h +++ b/core/Thread.h @@ -1,13 +1,19 @@ -/* $Id: Thread.h,v 1.19 2003/10/09 16:03:51 titer Exp $ +/* $Id: Thread.h,v 1.3 2003/11/06 15:51:36 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #ifndef HB_THREAD_H #define HB_THREAD_H -#include "Common.h" +#if defined( SYS_BEOS ) +# include <OS.h> +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) +# include <pthread.h> +#endif + +#include "Utils.h" #if defined( SYS_BEOS ) # define HB_LOW_PRIORITY 5 @@ -15,63 +21,52 @@ #elif defined( SYS_MACOSX ) # define HB_LOW_PRIORITY 0 # define HB_NORMAL_PRIORITY 31 -#elif defined( SYS_LINUX ) +#elif defined( SYS_LINUX ) || defined( SYS_CYGWIN ) /* Actually unused */ # define HB_LOW_PRIORITY 0 # define HB_NORMAL_PRIORITY 0 #endif -class HBThread -{ - public: - HBThread( char * name, - int priority = HB_LOW_PRIORITY ); - virtual ~HBThread(); - void Suspend(); - void Resume(); - int GetPid(); - - protected: - void Run(); - bool Push( HBFifo * fifo, HBBuffer * buffer ); - HBBuffer * Pop( HBFifo * fifo ); - - volatile bool fDie; - volatile bool fSuspend; - - private: - static void ThreadFunc( HBThread * _this ); - virtual void DoWork(); - - char * fName; - int fPriority; +HBThread * HBThreadInit( char * name, void (* function)(void *), + void * arg, int priority ); +void HBThreadClose( HBThread ** ); +struct HBLock +{ #if defined( SYS_BEOS ) - int fThread; + sem_id sem; #elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_t fThread; + pthread_mutex_t mutex; +#elif defined( SYS_CYGWIN ) + /* TODO */ #endif - int fPid; }; +HBLock * HBLockInit(); +static inline void HBLockLock( HBLock * ); +static inline void HBLockUnlock( HBLock * ); +void HBLockClose( HBLock ** ); + +static inline void HBLockLock( HBLock * l ) +{ #if defined( SYS_BEOS ) -class BLocker; + acquire_sem( l->sem ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + pthread_mutex_lock( &l->mutex ); +#elif defined( SYS_CYGWIN ) + /* TODO */ #endif +} -class HBLock +static inline void HBLockUnlock( HBLock * l ) { - public: - HBLock(); - ~HBLock(); - void Lock(); - void Unlock(); - - private: #if defined( SYS_BEOS ) - BLocker * fLocker; + release_sem( l->sem ); #elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) - pthread_mutex_t fMutex; + pthread_mutex_unlock( &l->mutex ); +#elif defined( SYS_CYGWIN ) + /* TODO */ #endif -}; +} #endif diff --git a/core/Utils.c b/core/Utils.c new file mode 100644 index 000000000..5f35ec3ae --- /dev/null +++ b/core/Utils.c @@ -0,0 +1,352 @@ +/* $Id: Utils.c,v 1.6 2003/11/06 15:51:36 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include <stdarg.h> +#include <time.h> +#include <sys/time.h> + +#include "Utils.h" +#include "Fifo.h" + +struct HBList +{ + void ** items; + int allocItems; + int nbItems; +}; + +void HBSnooze( int time ) +{ +#if defined( SYS_BEOS ) + snooze( time ); +#elif defined( SYS_MACOSX ) || defined( SYS_LINUX ) + usleep( time ); +#elif defined( SYS_CYGWIN ) + /* TODO */ +#endif +} + +void HBLog( char * log, ... ) +{ + char string[81]; + time_t _now; + struct tm * now; + va_list args; + int ret; + + if( !getenv( "HB_DEBUG" ) ) + { + return; + } + + /* Show the time */ + _now = time( NULL ); + now = localtime( &_now ); + sprintf( string, "[%02d:%02d:%02d] ", + now->tm_hour, now->tm_min, now->tm_sec ); + + /* Convert the message to a string */ + va_start( args, log ); + ret = vsnprintf( string + 11, 68, log, args ); + va_end( args ); + + /* Add the end of line */ + string[ret+11] = '\n'; + string[ret+12] = '\0'; + + /* Print it */ + fprintf( stderr, "%s", string ); +} + +uint64_t HBGetDate() +{ +#ifndef SYS_CYGWIN + struct timeval tv; + gettimeofday( &tv, NULL ); + return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec ); +#else + return 0; +#endif +} + +/* Basic MPEG demuxer - only works with DVDs ! (2048 bytes packets) */ +int HBPStoES( HBBuffer ** _psBuffer, HBList * esBufferList ) +{ + HBBuffer * psBuffer = *_psBuffer; + HBBuffer * esBuffer; + int pos = 0; + +#define d (psBuffer->data) + + /* pack_header */ + if( d[pos] != 0 || d[pos+1] != 0 || + d[pos+2] != 0x1 || d[pos+3] != 0xBA ) + { + HBLog( "HBPStoES: not a PS packet (%02x%02x%02x%02x)", + d[pos] << 24, d[pos+1] << 16, + d[pos+2] << 8, d[pos+3] ); + HBBufferClose( _psBuffer ); + return 0; + } + pos += 4; /* pack_start_code */ + pos += 9; /* pack_header */ + pos += 1 + ( d[pos] & 0x7 ); /* stuffing bytes */ + + /* system_header */ + if( d[pos] == 0 && d[pos+1] == 0 && + d[pos+2] == 0x1 && d[pos+3] == 0xBB ) + { + int header_length; + + pos += 4; /* system_header_start_code */ + header_length = ( d[pos] << 8 ) + d[pos+1]; + pos += 2 + header_length; + } + + /* PES */ + while( pos + 6 < psBuffer->size && + d[pos] == 0 && d[pos+1] == 0 && d[pos+2] == 0x1 ) + { + uint32_t streamId; + uint32_t PES_packet_length; + uint32_t PES_packet_end; + uint32_t PES_header_d_length; + uint32_t PES_header_end; + int hasPTS; + uint64_t PTS = 0; + + pos += 3; /* packet_start_code_prefix */ + streamId = d[pos]; + pos += 1; + + PES_packet_length = ( d[pos] << 8 ) + d[pos+1]; + pos += 2; /* PES_packet_length */ + PES_packet_end = pos + PES_packet_length; + + if( streamId != 0xE0 && streamId != 0xBD ) + { + /* Not interesting */ + pos = PES_packet_end; + continue; + } + + hasPTS = ( ( d[pos+1] >> 6 ) & 0x2 ) ? 1 : 0; + pos += 2; /* Required headers */ + + PES_header_d_length = d[pos]; + pos += 1; + PES_header_end = pos + PES_header_d_length; + + if( hasPTS ) + { + PTS = ( ( ( (uint64_t) d[pos] >> 1 ) & 0x7 ) << 30 ) + + ( d[pos+1] << 22 ) + + ( ( d[pos+2] >> 1 ) << 15 ) + + ( d[pos+3] << 7 ) + + ( d[pos+4] >> 1 ); + } + + pos = PES_header_end; + + if( streamId == 0xBD ) + { + /* A52: don't ask */ + streamId |= ( d[pos] << 8 ); + pos += 4; + } + + /* Sanity check */ + if( pos >= PES_packet_end ) + { + HBLog( "HBPStoES: pos >= PES_packet_end" ); + pos = PES_packet_end; + continue; + } + + /* Here we hit we ES payload */ + esBuffer = HBBufferInit( PES_packet_end - pos ); + + esBuffer->position = psBuffer->position; + esBuffer->pass = psBuffer->pass; + esBuffer->streamId = streamId; + esBuffer->pts = PTS; + memcpy( esBuffer->data, d + pos, + PES_packet_end - pos ); + + HBListAdd( esBufferList, esBuffer ); + + pos = PES_packet_end; + } + + HBBufferClose( _psBuffer ); + + return 1; +} + +#define HBLIST_DEFAULT_SIZE 20 +HBList * HBListInit() +{ + HBList * l; + if( !( l = malloc( sizeof( HBList ) ) ) ) + { + HBLog( "HBListInit: malloc() failed, gonna crash" ); + return NULL; + } + + if( !( l->items = malloc( HBLIST_DEFAULT_SIZE * sizeof( void* ) ) ) ) + { + HBLog( "HBListInit: malloc() failed, gonna crash" ); + free( l ); + return NULL; + } + + l->allocItems = HBLIST_DEFAULT_SIZE; + l->nbItems = 0; + + return l; +} + +int HBListCountItems( HBList * l ) +{ + return l->nbItems; +} + +void HBListAdd( HBList * l, void * item ) +{ + if( !item ) + { + return; + } + + if( l->nbItems == l->allocItems ) + { + l->allocItems += HBLIST_DEFAULT_SIZE; + l->items = realloc( l->items, + l->allocItems * sizeof( void* ) ); + } + + l->items[l->nbItems] = item; + (l->nbItems)++; +} + +void HBListRemove( HBList * l, void * item ) +{ + int i; + + if( !item || !l->nbItems ) + { + return; + } + + for( i = 0; i < l->nbItems; i++ ) + { + if( l->items[i] == item ) + { + break; + } + } + + if( l->items[i] != item ) + { + HBLog( "HBListRemove: specified item is not in the list" ); + return; + } + + for( ; i < l->nbItems - 1; i++ ) + { + l->items[i] = l->items[i+1]; + } + + (l->nbItems)--; +} + +void * HBListItemAt( HBList * l, int index ) +{ + if( index < 0 || index >= l->nbItems ) + { + return NULL; + } + + return l->items[index]; +} + +void HBListClose( HBList ** _l ) +{ + HBList * l = *_l; + + free( l->items ); + free( l ); + + *_l = NULL; +} + +HBTitle * HBTitleInit( char * device, int index ) +{ + HBTitle * t = calloc( sizeof( HBTitle ), 1 ); + + t->device = strdup( device ); + t->index = index; + + t->codec = HB_CODEC_FFMPEG; + t->bitrate = 1024; + + t->audioList = HBListInit(); + + return t; +} + +void HBTitleClose( HBTitle ** _t ) +{ + HBTitle * t = *_t; + + HBAudio * audio; + while( ( audio = HBListItemAt( t->audioList, 0 ) ) ) + { + HBListRemove( t->audioList, audio ); + HBAudioClose( &audio ); + } + HBListClose( &t->audioList ); + + if( t->file ) free( t->file ); + free( t->device ); + free( t ); + + *_t = NULL; +} + +HBAudio * HBAudioInit( int id, char * language ) +{ + HBAudio * a; + if( !( a = malloc( sizeof( HBAudio ) ) ) ) + { + HBLog( "HBAudioInit: malloc() failed, gonna crash" ); + return NULL; + } + + a->id = id; + a->language = strdup( language ); + a->inSampleRate = 0; + a->outSampleRate = 44100; + a->delay = 0; + a->ac3Fifo = NULL; + a->rawFifo = NULL; + a->mp3Fifo = NULL; + a->ac3Dec = NULL; + a->mp3Enc = NULL; + + return a; +} + +void HBAudioClose( HBAudio ** _a ) +{ + HBAudio * a = *_a; + + free( a->language ); + free( a ); + + *_a = NULL; +} + diff --git a/core/Utils.h b/core/Utils.h new file mode 100644 index 000000000..ba1a9101e --- /dev/null +++ b/core/Utils.h @@ -0,0 +1,213 @@ +/* $Id: Utils.h,v 1.6 2003/11/07 21:22:17 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_UTILS_H +#define HB_UTILS_H + +/* Standard headers */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <inttypes.h> +typedef uint8_t byte_t; +#ifdef SYS_BEOS +# include <OS.h> +#endif + +/* Handy macros */ +#ifndef MIN +#define MIN( a, b ) ( ( (a) > (b) ) ? (b) : (a) ) +#endif +#ifndef MAX +#define MAX( a, b ) ( ( (a) > (b) ) ? (a) : (b) ) +#endif +#ifndef EVEN +#define EVEN( a ) ( ( (a) & 0x1 ) ? ( (a) + 1 ) : (a) ) +#endif +#ifndef MULTIPLE_16 +#define MULTIPLE_16( a ) ( 16 * ( ( (a) + 8 ) / 16 ) ) +#endif +#ifndef VOUT_ASPECT_FACTOR +#define VOUT_ASPECT_FACTOR 432000 +#endif + +typedef struct HBAc3Dec HBAc3Dec; +typedef struct HBAudio HBAudio; +typedef struct HBAviMux HBAviMux; +typedef struct HBBuffer HBBuffer; +typedef struct HBDVDRead HBDVDRead; +typedef struct HBFifo HBFifo; +typedef struct HBList HBList; +typedef struct HBLock HBLock; +typedef struct HBHandle HBHandle; +typedef struct HBMp3Enc HBMp3Enc; +typedef struct HBMpeg2Dec HBMpeg2Dec; +typedef struct HBFfmpegEnc HBFfmpegEnc; +typedef struct HBMadDec HBMadDec; +typedef struct HBScale HBScale; +typedef struct HBScan HBScan; +typedef struct HBStatus HBStatus; +typedef struct HBThread HBThread; +typedef struct HBTitle HBTitle; +typedef struct HBWork HBWork; +typedef struct HBWorkThread HBWorkThread; +typedef struct HBXvidEnc HBXvidEnc; + +/* Misc functions which may be used from anywhere */ +void HBSnooze( int time ); +void HBLog( char * log, ... ); +uint64_t HBGetDate(); +int HBPStoES( HBBuffer ** psBuffer, HBList * esBufferList ); + +/* HBList functions */ +HBList * HBListInit(); +int HBListCountItems( HBList * ); +void HBListAdd( HBList *, void * item ); +void HBListRemove( HBList *, void * item ); +void * HBListItemAt( HBList *, int index ); +void HBListClose( HBList ** ); + +/* HBTitle function */ +HBTitle * HBTitleInit(); +void HBTitleClose( HBTitle ** ); + +/* HBAudio functions */ +HBAudio * HBAudioInit( int id, char * language ); +void HBAudioClose( HBAudio ** ); + +/* Possible states */ +typedef enum +{ + HB_MODE_UNDEF = 00000, + HB_MODE_NEED_DEVICE = 00001, + HB_MODE_SCANNING = 00002, + HB_MODE_INVALID_DEVICE = 00004, + HB_MODE_READY_TO_RIP = 00010, + HB_MODE_ENCODING = 00020, + HB_MODE_PAUSED = 00040, + HB_MODE_STOPPING = 00100, + HB_MODE_DONE = 00200, + HB_MODE_CANCELED = 00400, + HB_MODE_ERROR = 01000, + HB_MODE_EXITING = 02000 +} 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; + +/* Possible codecs */ +typedef enum +{ + HB_CODEC_FFMPEG = 0, + HB_CODEC_XVID +} HBCodec; + +struct HBStatus +{ + HBMode mode; + + /* HB_MODE_SCANNING */ + int scannedTitle; + + /* HB_MODE_SCANDONE */ + HBList * titleList; + + /* HB_MODE_ENCODING || HB_MODE_PAUSED */ + float position; + int pass; + int passCount; + float frameRate; + float avFrameRate; + uint32_t remainingTime; /* in seconds */ + + /* HB_MODE_ERROR */ + HBError error; +}; + +struct HBTitle +{ + char * device; + int index; + int length; + char * file; + + /* Video input */ + int inWidth; + int inHeight; + int aspect; + int rate; + int rateBase; + + /* Video output */ + int outWidth; + int outHeight; + int outWidthMax; + int outHeightMax; + int topCrop; + int bottomCrop; + int leftCrop; + int rightCrop; + int deinterlace; + HBCodec codec; + int bitrate; + int twoPass; + + /* Audio infos */ + HBList * audioList; + + /* Fifos */ + HBFifo * mpeg2Fifo; + HBFifo * rawFifo; + HBFifo * scaledFifo; + HBFifo * mpeg4Fifo; + + /* Threads */ + HBDVDRead * dvdRead; + HBMpeg2Dec * mpeg2Dec; + HBScale * scale; + HBFfmpegEnc * ffmpegEnc; + HBXvidEnc * xvidEnc; + HBAviMux * aviMux; + HBWorkThread * workThreads[8]; +}; + +struct HBAudio +{ + /* Ident */ + uint32_t id; + char * language; + + /* Settings */ + int inSampleRate; + int outSampleRate; + int inBitrate; + int outBitrate; + + int delay; /* in ms */ + + /* Fifos */ + HBFifo * ac3Fifo; + HBFifo * rawFifo; + HBFifo * mp3Fifo; + + /* Threads */ + HBAc3Dec * ac3Dec; + HBMp3Enc * mp3Enc; +}; + + + +#endif diff --git a/core/Work.c b/core/Work.c new file mode 100644 index 000000000..b15e50839 --- /dev/null +++ b/core/Work.c @@ -0,0 +1,187 @@ +/* $Id: Work.c,v 1.4 2003/11/06 12:33:11 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "Thread.h" +#include "Work.h" + +/* Local prototypes */ +static void WorkThread( void * t ); + +struct HBWork +{ + HB_WORK_COMMON_MEMBERS +}; + +struct HBWorkThread +{ + HBHandle * handle; + + HBList * workList; + int firstThread; + + int die; + HBThread * thread; +}; + +HBWorkThread * HBWorkThreadInit( HBHandle * handle, HBTitle * title, + HBAudio * audio, HBAudio * optAudio, + int firstThread ) +{ + int i; + HBWork * w; + + HBWorkThread * t; + if( !( t = malloc( sizeof( HBWorkThread ) ) ) ) + { + HBLog( "HBWorkThreadInit: malloc() failed, gonna crash" ); + return NULL; + } + + t->handle = handle; + + /* Build a list of work objects. They all include + HB_WORK_COMMON_MEMBERS, so we'll be able to do the job without + knowing what each one actually do */ + t->workList = HBListInit(); + HBListAdd( t->workList, title->mpeg2Dec ); + HBListAdd( t->workList, title->scale ); + + if( title->codec == HB_CODEC_FFMPEG ) + HBListAdd( t->workList, title->ffmpegEnc ); + else if( title->codec == HB_CODEC_XVID ) + HBListAdd( t->workList, title->xvidEnc ); + + HBListAdd( t->workList, audio->ac3Dec ); + HBListAdd( t->workList, audio->mp3Enc ); + if( optAudio ) + { + HBListAdd( t->workList, optAudio->ac3Dec ); + HBListAdd( t->workList, optAudio->mp3Enc ); + } + + t->firstThread = firstThread; + + /* Work objects are not thread-safe, so let's init locks so each + one can not be called anymore when it's doing something. This + is done by the first worker thread (see HBStartRip) */ + if( t->firstThread ) + { + for( i = 0; i < HBListCountItems( t->workList ); i++ ) + { + w = (HBWork*) HBListItemAt( t->workList, i ); + w->lock = HBLockInit(); + w->used = 0; + w->time = 0; + } + } + + /* Actually launch the thread */ + t->die = 0; + t->thread = HBThreadInit( "work thread", WorkThread, t, + HB_LOW_PRIORITY ); + + return t; +} + +void HBWorkThreadClose( HBWorkThread ** _t ) +{ + HBWorkThread * t = (*_t); + HBWork * w; + + /* Stop the thread */ + t->die = 1; + HBThreadClose( &t->thread ); + + /* Destroy locks, show stats */ + if( t->firstThread ) + { + int i; + uint64_t total = 0; + + for( i = 0; i < HBListCountItems( t->workList ); i++ ) + { + w = (HBWork*) HBListItemAt( t->workList, i ); + HBLockClose( &w->lock ); + total += w->time; + } + + for( i = 0; i < HBListCountItems( t->workList ); i++ ) + { + w = (HBWork*) HBListItemAt( t->workList, i ); + HBLog( "HBWorkThreadClose: %- 9s = %05.2f %%", w->name, + 100.0 * w->time / total ); + } + + } + + /* Free memory */ + HBListClose( &t->workList ); + free( t ); + + (*_t) = NULL; +} + +static void WorkThread( void * _t ) +{ + HBWorkThread * t = (HBWorkThread*) _t; + HBWork * w; + int didSomething, i; + uint64_t date; + + for( ;; ) + { + HBCheckPaused( t->handle ); + + didSomething = 0; + + for( i = 0; i < HBListCountItems( t->workList ); i++ ) + { + if( t->die ) + { + break; + } + + w = (HBWork*) HBListItemAt( t->workList, i ); + + /* Check if another thread isn't using this work object. + If not, lock it */ + HBLockLock( w->lock ); + if( w->used ) + { + HBLockUnlock( w->lock ); + continue; + } + w->used = 1; + HBLockUnlock( w->lock ); + + /* Actually do the job */ + date = HBGetDate(); + if( w->work( w ) ) + { + w->time += HBGetDate() - date; + didSomething = 1; + } + + /* Unlock */ + HBLockLock( w->lock ); + w->used = 0; + HBLockUnlock( w->lock ); + } + + if( t->die ) + { + break; + } + + /* If nothing could be done, wait a bit to prevent a useless + CPU-consuming loop */ + if( !didSomething ) + { + HBSnooze( 10000 ); + } + } +} + diff --git a/core/Work.h b/core/Work.h new file mode 100644 index 000000000..8d3cfba15 --- /dev/null +++ b/core/Work.h @@ -0,0 +1,27 @@ +/* $Id: Work.h,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_WORK_H +#define HB_WORK_H + +#include "HandBrakeInternal.h" + +#define HB_WORK_COMMON_MEMBERS \ + char * name; \ + HBLock * lock; \ + int used; \ + uint64_t time; \ + int (*work) ( HBWork * ); + +void HBWorkLock( HBWork * ); +void HBWorkWork( HBWork * ); +void HBWorkUnlock( HBWork * ); + +HBWorkThread * HBWorkThreadInit( HBHandle *, HBTitle *, HBAudio *, + HBAudio *, int firstThread ); +void HBWorkThreadClose( HBWorkThread ** ); + +#endif diff --git a/core/Worker.cpp b/core/Worker.cpp deleted file mode 100644 index 4310e46f4..000000000 --- a/core/Worker.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/* $Id: Worker.cpp,v 1.11 2003/10/16 13:36:17 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#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; - - for( ;; ) - { - while( fSuspend ) - { - Snooze( 10000 ); - } - - 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 ); - } - } - - tmpDate = mpegDemux + mpeg2Decoder + resizer + mpeg4Encoder + - ac3Decoder1 + mp3Encoder1 + ac3Decoder2 + mp3Encoder2; - Log( "HBWorker stopped. CPU utilization:" ); - Log( "- MPEG demuxer: %.2f %%", 100.0 * mpegDemux / tmpDate ); - Log( "- MPEG-2 decoder: %.2f %%", 100.0 * mpeg2Decoder / tmpDate ); - Log( "- Resizer: %.2f %%", 100.0 * resizer / tmpDate ); - Log( "- MPEG-4 encoder: %.2f %%", 100.0 * mpeg4Encoder / tmpDate ); - if( fAudio1 ) - { - Log( "- AC3 decoder 1: %.2f %%", 100.0 * ac3Decoder1 / tmpDate ); - Log( "- MP3 encoder 1: %.2f %%", 100.0 * mp3Encoder1 / tmpDate ); - } - if( fAudio2 ) - { - Log( "- AC3 decoder 2: %.2f %%", 100.0 * ac3Decoder2 / tmpDate ); - Log( "- MP3 encoder 2: %.2f %%", 100.0 * mp3Encoder2 / tmpDate ); - } -} - diff --git a/core/Worker.h b/core/Worker.h deleted file mode 100644 index 5df8f648b..000000000 --- a/core/Worker.h +++ /dev/null @@ -1,28 +0,0 @@ -/* $Id: Worker.h,v 1.3 2003/10/16 13:36:17 titer Exp $ - - This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. - It may be used under the terms of the GNU General Public License. */ - -#ifndef HB_WORKER_H -#define HB_WORKER_H - -#include "Common.h" -#include "Thread.h" - -class HBWorker : public HBThread -{ - public: - HBWorker( HBTitle * title, HBAudio * audio1, - HBAudio * audio2 ); - void WaitUntilDone(); - - private: - void DoWork(); - - HBTitle * fTitle; - HBAudio * fAudio1; - HBAudio * fAudio2; -}; - -#endif diff --git a/core/XvidEnc.c b/core/XvidEnc.c new file mode 100644 index 000000000..8f16ad4ba --- /dev/null +++ b/core/XvidEnc.c @@ -0,0 +1,170 @@ +/* $Id: XvidEnc.c,v 1.5 2003/11/05 19:14:37 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include "XvidEnc.h" +#include "Fifo.h" +#include "Work.h" + +#include <xvid.h> + +/* Local prototypes */ +static int XvidEncWork( HBWork * ); + +struct HBXvidEnc +{ + HB_WORK_COMMON_MEMBERS + + HBHandle * handle; + HBTitle * title; + + void * xvid; + HBBuffer * mpeg4Buffer; + int pass; +}; + +HBXvidEnc * HBXvidEncInit( HBHandle * handle, HBTitle * title ) +{ + HBXvidEnc * x; + if( !( x = malloc( sizeof( HBXvidEnc ) ) ) ) + { + HBLog( "HBXvidEncInit: malloc() failed, gonna crash" ); + return NULL; + } + + x->name = strdup( "XvidEnc" ); + x->work = XvidEncWork; + + x->handle = handle; + x->title = title; + + x->xvid = NULL; + x->mpeg4Buffer = NULL; + x->pass = 42; + + return x; +} + +void HBXvidEncClose( HBXvidEnc ** _x ) +{ + HBXvidEnc * x = *_x; + free( x ); + *_x = NULL; +} + +static int XvidEncWork( HBWork * w ) +{ + HBXvidEnc * x = (HBXvidEnc*) w; + HBTitle * title = x->title; + HBBuffer * scaledBuffer; + HBBuffer * mpeg4Buffer; + XVID_ENC_FRAME xframe; + + int didSomething = 0; + + if( x->mpeg4Buffer ) + { + if( HBFifoPush( title->mpeg4Fifo, &x->mpeg4Buffer ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + } + + if( ( scaledBuffer = HBFifoPop( title->scaledFifo ) ) ) + { + didSomething = 1; + } + else + { + return didSomething; + } + + /* Init or re-init if needed */ + if( scaledBuffer->pass != x->pass ) + { + XVID_INIT_PARAM xinit; + XVID_ENC_PARAM xparam; + + x->pass = scaledBuffer->pass;; + + HBLog( "HBXvidEnc: opening libxvidcore (pass %d)", x->pass ); + + xinit.cpu_flags = 0; + xvid_init( NULL, 0, &xinit, NULL ); + + xparam.width = title->outWidth; + xparam.height = title->outHeight; + + xparam.fincr = title->rateBase; + xparam.fbase = title->rate; + + xparam.rc_bitrate = title->bitrate * 1000; + + /* Default values should be ok */ + xparam.rc_reaction_delay_factor = -1; + xparam.rc_averaging_period = -1; + xparam.rc_buffer = -1; + xparam.max_quantizer = -1; + xparam.min_quantizer = -1; + xparam.max_key_interval = -1; + + if( xvid_encore( NULL, XVID_ENC_CREATE, &xparam, NULL ) ) + { + HBLog( "HBXvidEnc: xvid_encore() failed" ); + } + + x->xvid = xparam.handle; + } + + /* TODO implement 2-pass encoding */ + if( x->pass == 1 ) + { + HBPosition( x->handle, scaledBuffer->position ); + HBBufferClose( &scaledBuffer ); + return didSomething; + } + + mpeg4Buffer = HBBufferInit( title->outWidth * + title->outHeight * 3 / 2 ); + mpeg4Buffer->position = scaledBuffer->position; + + xframe.general = XVID_H263QUANT | XVID_HALFPEL | XVID_INTER4V; + xframe.motion = PMV_EARLYSTOP16 | PMV_HALFPELREFINE16 | + PMV_EXTSEARCH16 | PMV_EARLYSTOP8 | + PMV_HALFPELREFINE8 | PMV_HALFPELDIAMOND8 | + PMV_USESQUARES16; + xframe.bitstream = mpeg4Buffer->data; + + xframe.image = scaledBuffer->data; + xframe.colorspace = XVID_CSP_I420; + + xframe.quant_intra_matrix = NULL; + xframe.quant_inter_matrix = NULL; + xframe.quant = 0; + xframe.intra = -1; + + xframe.hint.hintstream = NULL; + + if( xvid_encore( x->xvid, XVID_ENC_ENCODE, &xframe, NULL ) ) + { + HBLog( "HBXvidEnc: xvid_encore() failed" ); + } + + mpeg4Buffer->size = xframe.length; + mpeg4Buffer->keyFrame = xframe.intra; + + /* Inform the GUI about the current position */ + HBPosition( x->handle, scaledBuffer->position ); + + HBBufferClose( &scaledBuffer ); + x->mpeg4Buffer = mpeg4Buffer; + + return didSomething; +} + diff --git a/core/XvidEnc.h b/core/XvidEnc.h new file mode 100644 index 000000000..01cb6f4d4 --- /dev/null +++ b/core/XvidEnc.h @@ -0,0 +1,15 @@ +/* $Id: XvidEnc.h,v 1.1 2003/11/03 12:08:01 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#ifndef HB_XVID_ENC_H +#define HB_XVID_ENC_H + +#include "HandBrakeInternal.h" + +HBXvidEnc * HBXvidEncInit( HBHandle *, HBTitle * ); +void HBXvidEncClose( HBXvidEnc ** ); + +#endif diff --git a/macosx/Controller.h b/macosx/Controller.h index 4759a1d5b..469994c68 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -1,12 +1,12 @@ -/* $Id: Controller.h,v 1.6 2003/10/13 23:09:56 titer Exp $ +/* $Id: Controller.h,v 1.4 2003/11/07 21:22:17 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <Cocoa/Cocoa.h> -#include "Common.h" +#include "HandBrake.h" #include "PictureGLView.h" #include "TargetSizeField.h" @@ -18,7 +18,6 @@ IBOutlet NSWindow * fWindow; /* Scan view */ - uint64_t fLastDVDDetection; IBOutlet NSView * fScanView; IBOutlet NSMatrix * fScanMatrix; IBOutlet NSPopUpButton * fDVDPopUp; @@ -63,7 +62,7 @@ /* "Done" alert panel */ IBOutlet NSPanel * fDonePanel; - /* Crop & resize panel */ + /* Crop & scale panel */ IBOutlet NSPanel * fPicturePanel; IBOutlet HBPictureGLView * fPictureGLView; IBOutlet NSTextField * fWidthField; @@ -78,9 +77,12 @@ IBOutlet NSTextField * fRightField; IBOutlet NSStepper * fRightStepper; IBOutlet NSTextField * fInfoField; + IBOutlet NSButton * fOpenGLCheck; + IBOutlet NSButton * fPreviousButton; + IBOutlet NSButton * fNextButton; int fPicture; - HBManager * fManager; + HBHandle * fHandle; HBList * fTitleList; } @@ -91,6 +93,7 @@ - (IBAction) Scan: (id) sender; - (IBAction) TitlePopUpChanged: (id) sender; +- (IBAction) VideoCodecPopUpChanged: (id) sender; - (IBAction) VideoMatrixChanged: (id) sender; - (IBAction) AudioPopUpChanged: (id) sender; - (IBAction) BrowseFile: (id) sender; @@ -111,6 +114,6 @@ - (IBAction) UpdatePicture: (id) sender; - (void) UpdateIntf: (NSTimer *) timer; -- (void) DetectDrives; +- (void) DetectDrives: (NSNotification *) notification; @end diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 402d721fa..a345bdec1 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -1,7 +1,7 @@ -/* $Id: Controller.mm,v 1.10 2003/10/13 23:09:56 titer Exp $ +/* $Id: Controller.mm,v 1.7 2003/11/07 21:22:17 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <paths.h> @@ -11,20 +11,25 @@ #include <IOKit/storage/IODVDMedia.h> #include "Controller.h" -#include "Manager.h" @implementation HBController - (void) applicationDidFinishLaunching: (NSNotification *) notification { /* Init libhb */ - fManager = new HBManager( true ); + fHandle = HBInit( 1, 0 ); + [fPictureGLView SetHandle: fHandle]; /* Update the GUI every 1/10 sec */ fDie = false; [NSTimer scheduledTimerWithTimeInterval: 0.1 target: self selector: @selector( UpdateIntf: ) userInfo: nil repeats: YES]; + + /* Detect drives mounted after the app is started */ + [[[NSWorkspace sharedWorkspace] notificationCenter] + addObserver: self selector: @selector( DetectDrives: ) + name: NSWorkspaceDidMountNotification object: nil]; } - (NSApplicationTerminateReply) applicationShouldTerminate: @@ -32,7 +37,7 @@ { /* Clean up */ fDie = true; - delete fManager; + HBClose( &fHandle ); return NSTerminateNow; } @@ -42,6 +47,10 @@ [fDVDPopUp removeAllItems]; [fScanProgress setStyle: NSProgressIndicatorSpinningStyle]; [fScanProgress setDisplayedWhenStopped: NO]; + [fVideoCodecPopUp removeAllItems]; + [fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (Ffmpeg)"]; + [fVideoCodecPopUp addItemWithTitle: @"MPEG-4 (XviD)"]; + [fVideoCodecPopUp selectItemWithTitle: @"MPEG-4 (Ffmpeg)"]; [fAudioBitratePopUp removeAllItems]; [fAudioBitratePopUp addItemWithTitle: @"32"]; [fAudioBitratePopUp addItemWithTitle: @"64"]; @@ -65,8 +74,7 @@ [fWindow center]; /* Detect DVD drives */ - fLastDVDDetection = GetDate(); - [self DetectDrives]; + [self DetectDrives: nil]; [self ScanMatrixChanged: self]; } @@ -139,76 +147,82 @@ - (IBAction) Scan: (id) sender { - /* Ask the manager to start scanning the specified volume */ + /* Ask libhb to start scanning the specified volume */ if( ![fScanMatrix selectedRow] ) { /* DVD drive */ - fManager->ScanVolumes( (char*) [[fDVDPopUp titleOfSelectedItem] - cString] ); + HBScanDevice( fHandle, + (char*) [[fDVDPopUp titleOfSelectedItem] cString], + 0 ); } else { /* DVD folder */ - fManager->ScanVolumes( (char*) [[fDVDFolderField stringValue] - cString] ); + HBScanDevice( fHandle, + (char*) [[fDVDFolderField stringValue] cString], + 0 ); } } - (IBAction) ShowPicturePanel: (id) sender { HBTitle * title = (HBTitle*) - fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); + HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); - [fPictureGLView SetManager: fManager]; [fPictureGLView SetTitle: title]; fPicture = 0; - [fPictureGLView ShowPicture: fPicture]; + [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE]; [fWidthStepper setValueWraps: NO]; [fWidthStepper setIncrement: 16]; [fWidthStepper setMinValue: 16]; - [fWidthStepper setMaxValue: title->fOutWidthMax]; - [fWidthStepper setIntValue: title->fOutWidth]; - [fWidthField setIntValue: title->fOutWidth]; - [fTopStepper setValueWraps: NO]; + [fWidthStepper setMaxValue: title->outWidthMax]; + [fWidthStepper setIntValue: title->outWidth]; + [fWidthField setIntValue: title->outWidth]; + [fDeinterlaceCheck setState: + title->deinterlace ? NSOnState : NSOffState]; + [fTopStepper setValueWraps: NO]; [fTopStepper setIncrement: 2]; [fTopStepper setMinValue: 0]; - [fTopStepper setMaxValue: title->fInHeight / 4]; - [fTopStepper setIntValue: title->fTopCrop]; - [fTopField setIntValue: title->fTopCrop]; + [fTopStepper setMaxValue: title->inHeight / 4]; + [fTopStepper setIntValue: title->topCrop]; + [fTopField setIntValue: title->topCrop]; [fBottomStepper setValueWraps: NO]; [fBottomStepper setIncrement: 2]; [fBottomStepper setMinValue: 0]; - [fBottomStepper setMaxValue: title->fInHeight / 4]; - [fBottomStepper setIntValue: title->fBottomCrop]; - [fBottomField setIntValue: title->fBottomCrop]; + [fBottomStepper setMaxValue: title->inHeight / 4]; + [fBottomStepper setIntValue: title->bottomCrop]; + [fBottomField setIntValue: title->bottomCrop]; [fLeftStepper setValueWraps: NO]; [fLeftStepper setIncrement: 2]; [fLeftStepper setMinValue: 0]; - [fLeftStepper setMaxValue: title->fInWidth / 4]; - [fLeftStepper setIntValue: title->fLeftCrop]; - [fLeftField setIntValue: title->fLeftCrop]; + [fLeftStepper setMaxValue: title->inWidth / 4]; + [fLeftStepper setIntValue: title->leftCrop]; + [fLeftField setIntValue: title->leftCrop]; [fRightStepper setValueWraps: NO]; [fRightStepper setIncrement: 2]; [fRightStepper setMinValue: 0]; - [fRightStepper setMaxValue: title->fInWidth / 4]; - [fRightStepper setIntValue: title->fRightCrop]; - [fRightField setIntValue: title->fRightCrop]; + [fRightStepper setMaxValue: title->inWidth / 4]; + [fRightStepper setIntValue: title->rightCrop]; + [fRightField setIntValue: title->rightCrop]; + + [fPreviousButton setEnabled: NO]; + [fNextButton setEnabled: YES]; char string[1024]; memset( string, 0, 1024 ); sprintf( string, "Final size: %dx%d", - title->fOutWidth, title->fOutHeight ); + title->outWidth, title->outHeight ); [fInfoField setStringValue: [NSString stringWithCString: string]]; /* Resize the panel */ NSSize newSize; /* XXX */ newSize.width = 762 /*fPicturePanelSize.width*/ + - title->fOutWidthMax - 720; + title->outWidthMax - 720; newSize.height = 740 /*fPicturePanelSize.height*/ + - title->fOutHeightMax - 576; + title->outHeightMax - 576; [fPicturePanel setContentSize: newSize]; [NSApp beginSheet: fPicturePanel modalForWindow: fWindow @@ -260,10 +274,10 @@ { fclose( file ); NSBeginCriticalAlertSheet( @"File already exists", - @"Nooo", @"Yes, go ahead!", nil, fWindow, self, + @"Nooo!", @"Yes, go ahead", nil, fWindow, self, @selector( OverwriteAlertDone:returnCode:contextInfo: ), nil, nil, - [NSString stringWithFormat: @"Do you want to overwrite %s ?", + [NSString stringWithFormat: @"Do you want to overwrite %s?", [[fFileField stringValue] cString]] ); return; } @@ -284,32 +298,36 @@ { /* Get the specified title & audio track(s) */ HBTitle * title = (HBTitle*) - fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); + HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); HBAudio * audio1 = (HBAudio*) - title->fAudioList->ItemAt( [fLanguagePopUp indexOfSelectedItem] ); + HBListItemAt( title->audioList, + [fLanguagePopUp indexOfSelectedItem] ); HBAudio * audio2 = (HBAudio*) - title->fAudioList->ItemAt( [fSecondaryLanguagePopUp - indexOfSelectedItem] ); + HBListItemAt( title->audioList, + [fSecondaryLanguagePopUp indexOfSelectedItem] ); /* Use user settings */ - title->fBitrate = [fCustomBitrateField intValue]; - title->fTwoPass = ( [fTwoPassCheck state] == NSOnState ); - audio1->fOutBitrate = [[fAudioBitratePopUp titleOfSelectedItem] + title->file = strdup( [[fFileField stringValue] cString] ); + title->bitrate = [fCustomBitrateField intValue]; + title->twoPass = ( [fTwoPassCheck state] == NSOnState ); + title->codec = ( [[fVideoCodecPopUp titleOfSelectedItem] compare: + @"MPEG-4 (Ffmpeg)"] == NSOrderedSame ) ? + HB_CODEC_FFMPEG : HB_CODEC_XVID; + audio1->outBitrate = [[fAudioBitratePopUp titleOfSelectedItem] intValue]; if( audio2 ) { - audio2->fOutBitrate = + audio2->outBitrate = [[fAudioBitratePopUp titleOfSelectedItem] intValue]; } /* Let libhb do the job */ - fManager->StartRip( title, audio1, audio2, - (char*) [[fFileField stringValue] cString] ); + HBStartRip( fHandle, title, audio1, audio2 ); } - (IBAction) Cancel: (id) sender { - fManager->StopRip(); + HBStopRip( fHandle ); } - (IBAction) Suspend: (id) sender @@ -320,50 +338,68 @@ return; } - fManager->SuspendRip(); + HBPauseRip( fHandle ); } - (IBAction) Resume: (id) sender { - fManager->ResumeRip(); + HBResumeRip( fHandle ); } - (IBAction) PreviousPicture: (id) sender { - if( fPicture > 0 ) + fPicture--; + if( [fOpenGLCheck state] == NSOnState ) { - fPicture--; - [fPictureGLView ShowPicture: fPicture]; + [fPictureGLView ShowPicture: fPicture + animate: HB_ANIMATE_LEFT]; } + else + { + [fPictureGLView ShowPicture: fPicture + animate: HB_ANIMATE_NONE]; + } + + [fPreviousButton setEnabled: ( fPicture > 0 )]; + [fNextButton setEnabled: YES]; } - (IBAction) NextPicture: (id) sender { - if( fPicture < 9 ) + fPicture++; + if( [fOpenGLCheck state] == NSOnState ) + { + [fPictureGLView ShowPicture: fPicture + animate: HB_ANIMATE_RIGHT]; + } + else { - fPicture++; - [fPictureGLView ShowPicture: fPicture]; + [fPictureGLView ShowPicture: fPicture + animate: HB_ANIMATE_NONE]; } + + [fPreviousButton setEnabled: YES]; + [fNextButton setEnabled: ( fPicture < 9 )]; } - (IBAction) UpdatePicture: (id) sender { HBTitle * title = (HBTitle*) - fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); - title->fOutWidth = [fWidthStepper intValue]; - title->fDeinterlace = ( [fDeinterlaceCheck state] == NSOnState ); - title->fTopCrop = [fTopStepper intValue]; - title->fBottomCrop = [fBottomStepper intValue]; - title->fLeftCrop = [fLeftStepper intValue]; - title->fRightCrop = [fRightStepper intValue]; - - [fPictureGLView ShowPicture: fPicture]; - - [fWidthStepper setIntValue: title->fOutWidth]; - [fTopStepper setIntValue: title->fTopCrop]; - [fBottomStepper setIntValue: title->fBottomCrop]; - [fLeftStepper setIntValue: title->fLeftCrop]; - [fRightStepper setIntValue: title->fRightCrop]; + HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); + title->outWidth = [fWidthStepper intValue]; + title->deinterlace = ( [fDeinterlaceCheck state] == NSOnState ); + title->topCrop = [fTopStepper intValue]; + title->bottomCrop = [fBottomStepper intValue]; + title->leftCrop = [fLeftStepper intValue]; + title->rightCrop = [fRightStepper intValue]; + + [fPictureGLView ShowPicture: fPicture animate: HB_ANIMATE_NONE]; + + [fWidthStepper setIntValue: title->outWidth]; + [fTopStepper setIntValue: title->topCrop]; + [fBottomStepper setIntValue: title->bottomCrop]; + [fLeftStepper setIntValue: title->leftCrop]; + [fRightStepper setIntValue: title->rightCrop]; [fWidthField setIntValue: [fWidthStepper intValue]]; [fTopField setIntValue: [fTopStepper intValue]]; [fBottomField setIntValue: [fBottomStepper intValue]]; @@ -372,7 +408,7 @@ char string[1024]; memset( string, 0, 1024 ); sprintf( string, "Final size: %dx%d", - title->fOutWidth, title->fOutHeight ); + title->outWidth, title->outHeight ); [fInfoField setStringValue: [NSString stringWithCString: string]]; } @@ -384,25 +420,19 @@ 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() ) + int modeChanged; + HBStatus status; + + modeChanged = HBGetStatus( fHandle, &status ); + + switch( status.mode ) { - HBStatus status = fManager->GetStatus(); + case HB_MODE_NEED_DEVICE: + break; - switch( status.fMode ) + case HB_MODE_SCANNING: { - case HB_MODE_NEED_VOLUME: - break; - - case HB_MODE_SCANNING: + if( modeChanged ) { [fScanMatrix setEnabled: NO]; [fDVDPopUp setEnabled: NO]; @@ -410,81 +440,88 @@ [fScanBrowseButton setEnabled: NO]; [fScanProgress startAnimation: self]; [fScanButton setEnabled: NO]; - - char string[1024]; memset( string, 0, 1024 ); - if( status.fScannedTitle ) - { - sprintf( string, "Scanning %s, title %d...", - status.fScannedVolume, - status.fScannedTitle ); - } - else - { - sprintf( string, "Opening %s...", - status.fScannedVolume ); - } - [fScanStatusField setStringValue: - [NSString stringWithCString: string]]; - - break; } - case HB_MODE_INVALID_VOLUME: + char string[1024]; memset( string, 0, 1024 ); + if( status.scannedTitle ) + { + sprintf( string, "Scanning title %d...", + status.scannedTitle ); + } + else { - [fScanMatrix setEnabled: YES]; - [self ScanMatrixChanged: self]; - [fScanProgress stopAnimation: self]; - [fScanButton setEnabled: YES]; + sprintf( string, "Opening device..." ); + } + [fScanStatusField setStringValue: + [NSString stringWithCString: string]]; + + break; + } - [fScanStatusField setStringValue: - @"Invalid volume, try again" ]; + case HB_MODE_INVALID_DEVICE: + { + if( !modeChanged ) break; - } + + [fScanMatrix setEnabled: YES]; + [self ScanMatrixChanged: self]; + [fScanProgress stopAnimation: self]; + [fScanButton setEnabled: YES]; + + [fScanStatusField setStringValue: + @"Invalid volume, try again" ]; + break; + } - case HB_MODE_READY_TO_RIP: - { - fTitleList = status.fTitleList; - - /* Show a temporary empty view while the window - resizing animation */ - [fWindow setContentView: fTempView ]; - - /* Actually resize it */ - NSRect newFrame; - newFrame = [NSWindow contentRectForFrameRect: [fWindow frame] - styleMask: [fWindow styleMask]]; - newFrame.origin.y += newFrame.size.height - - [fRipView frame].size.height; - newFrame.size.height = [fRipView frame].size.height; - newFrame.size.width = [fRipView frame].size.width; - newFrame = [NSWindow frameRectForContentRect: newFrame - styleMask: [fWindow styleMask]]; - [fWindow setFrame: newFrame display: YES animate: YES]; - - /* Show the new GUI */ - [fWindow setContentView: fRipView ]; - [fSuspendButton setEnabled: NO]; - - [fTitlePopUp removeAllItems]; - HBTitle * title; - for( uint32_t i = 0; i < fTitleList->CountItems(); i++ ) - { - title = (HBTitle*) fTitleList->ItemAt( i ); - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "%d (%02lld:%02lld:%02lld)", - title->fIndex, title->fLength / 3600, - ( title->fLength % 3600 ) / 60, - title->fLength % 60 ); - [[fTitlePopUp menu] addItemWithTitle: - [NSString stringWithCString: string] - action: nil keyEquivalent: @""]; - } - [self TitlePopUpChanged: self]; - + case HB_MODE_READY_TO_RIP: + { + if( !modeChanged ) break; + + fTitleList = status.titleList; + + /* Show a temporary empty view while the window + resizing animation */ + [fWindow setContentView: fTempView ]; + + /* Actually resize it */ + NSRect newFrame; + newFrame = [NSWindow contentRectForFrameRect: [fWindow frame] + styleMask: [fWindow styleMask]]; + newFrame.origin.y += newFrame.size.height - + [fRipView frame].size.height; + newFrame.size.height = [fRipView frame].size.height; + newFrame.size.width = [fRipView frame].size.width; + newFrame = [NSWindow frameRectForContentRect: newFrame + styleMask: [fWindow styleMask]]; + [fWindow setFrame: newFrame display: YES animate: YES]; + + /* Show the new GUI */ + [fWindow setContentView: fRipView ]; + [fSuspendButton setEnabled: NO]; + + [fTitlePopUp removeAllItems]; + HBTitle * title; + for( int i = 0; i < HBListCountItems( fTitleList ); i++ ) + { + title = (HBTitle*) HBListItemAt( fTitleList, i ); + char string[1024]; memset( string, 0, 1024 ); + sprintf( string, "%d - %02dh%02dm%02ds", + title->index, title->length / 3600, + ( title->length % 3600 ) / 60, + title->length % 60 ); + [[fTitlePopUp menu] addItemWithTitle: + [NSString stringWithCString: string] + action: nil keyEquivalent: @""]; } + [self TitlePopUpChanged: self]; + + break; + } - case HB_MODE_ENCODING: + case HB_MODE_ENCODING: + { + if( modeChanged ) { [fTitlePopUp setEnabled: NO]; [fVideoCodecPopUp setEnabled: NO]; @@ -502,150 +539,161 @@ [fSuspendButton setEnabled: YES]; [fSuspendButton setTitle: @"Suspend"]; [fRipButton setTitle: @"Cancel"]; - - if( !status.fPosition ) - { - [fRipStatusField setStringValue: @"Starting..."]; - [fRipProgress setIndeterminate: YES]; - [fRipProgress startAnimation: self];; - } - else - { - 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 ); - [fRipInfoField setStringValue: - [NSString stringWithCString: string]]; - - [fRipProgress setIndeterminate: NO]; - [fRipProgress setDoubleValue: 100 * status.fPosition]; - } - - break; } - - case HB_MODE_SUSPENDED: + + if( !status.position ) { - char string[1024]; memset( string, 0, 1024 ); - sprintf( string, "Encoding: %.2f %% (PAUSED)", - 100 * status.fPosition ) ; + [fRipStatusField setStringValue: @"Starting..."]; + [fRipProgress setIndeterminate: YES]; + [fRipProgress startAnimation: self];; + } + else + { + char string[1024]; + memset( string, 0, 1024 ); + sprintf( string, "Encoding: %.2f %% (pass %d of %d)", + 100 * status.position, status.pass, + status.passCount ); [fRipStatusField setStringValue: [NSString stringWithCString: string]]; - [fRipInfoField setStringValue: @""]; - - [fRipProgress setDoubleValue: 100 * status.fPosition]; + memset( string, 0, 1024 ); + sprintf( string, "Speed: %.2f fps (avg %.2f fps, " + "%02dh%02dm%02ds remaining)", + status.frameRate, status.avFrameRate, + status.remainingTime / 3600, + ( status.remainingTime / 60 ) % 60, + status.remainingTime % 60 ); + [fRipInfoField setStringValue: + [NSString stringWithCString: string]]; - [fSuspendButton setTitle: @"Resume"]; - break; + [fRipProgress setIndeterminate: NO]; + [fRipProgress setDoubleValue: 100 * status.position]; } + + break; + } - case HB_MODE_STOPPING: - [fRipStatusField setStringValue: @"Stopping..."]; - [fRipInfoField setStringValue: @""]; - [fRipProgress setIndeterminate: YES]; - [fRipProgress startAnimation: self];; + case HB_MODE_PAUSED: + { + if( !modeChanged ) break; + + char string[1024]; memset( string, 0, 1024 ); + sprintf( string, "Encoding: %.2f %% (PAUSED)", + 100 * status.position ) ; + [fRipStatusField setStringValue: + [NSString stringWithCString: string]]; + [fRipInfoField setStringValue: @""]; + + [fRipProgress setDoubleValue: 100 * status.position]; - case HB_MODE_DONE: - case HB_MODE_CANCELED: - case HB_MODE_ERROR: - [fRipProgress setIndeterminate: NO]; - - if( status.fMode == HB_MODE_DONE ) - { - [fRipProgress setDoubleValue: 100]; - [fRipStatusField setStringValue: @"Done." ]; - NSBeep(); - [NSApp requestUserAttention: NSInformationalRequest]; - [NSApp beginSheet: fDonePanel - modalForWindow: fWindow modalDelegate: nil - didEndSelector: nil contextInfo: nil]; - [NSApp runModalForWindow: fDonePanel]; - [NSApp endSheet: fDonePanel]; - [fDonePanel orderOut: self]; - } - else if( status.fMode == HB_MODE_CANCELED ) - { - [fRipProgress setDoubleValue: 0]; - [fRipStatusField setStringValue: @"Canceled." ]; - } - else - { - [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; - } - } + [fSuspendButton setTitle: @"Resume"]; + 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"]; + case HB_MODE_STOPPING: + if( !modeChanged ) + break; - [self VideoMatrixChanged: self]; + [fRipStatusField setStringValue: @"Stopping..."]; + [fRipInfoField setStringValue: @""]; + [fRipProgress setIndeterminate: YES]; + [fRipProgress startAnimation: self];; + break; - /* Warn the finder to update itself */ - [[NSWorkspace sharedWorkspace] noteFileSystemChanged: - [fFileField stringValue]]; + case HB_MODE_DONE: + case HB_MODE_CANCELED: + case HB_MODE_ERROR: + if( !modeChanged ) break; - default: - break; - } + /* Warn the finder to update itself */ + [[NSWorkspace sharedWorkspace] noteFileSystemChanged: + [fFileField stringValue]]; + + [fRipProgress setIndeterminate: NO]; + [fRipInfoField setStringValue: @""]; + + if( status.mode == HB_MODE_DONE ) + { + [fRipProgress setDoubleValue: 100]; + [fRipStatusField setStringValue: @"Done." ]; + NSBeep(); + [NSApp requestUserAttention: NSInformationalRequest]; + [NSApp beginSheet: fDonePanel + modalForWindow: fWindow modalDelegate: nil + didEndSelector: nil contextInfo: nil]; + [NSApp runModalForWindow: fDonePanel]; + [NSApp endSheet: fDonePanel]; + [fDonePanel orderOut: self]; + } + else if( status.mode == HB_MODE_CANCELED ) + { + [fRipProgress setDoubleValue: 0]; + [fRipStatusField setStringValue: @"Canceled." ]; + } + else + { + [fRipProgress setDoubleValue: 0]; + switch( status.error ) + { + 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; + } + } + + [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]; + [self VideoCodecPopUpChanged: self]; + + break; + + default: + break; } } -- (void) DetectDrives +- (void) DetectDrives: (NSNotification *) notification { /* Scan DVD drives (stolen from VLC) */ io_object_t next_media; @@ -666,7 +714,7 @@ return; } - CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectable ), + CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue ); kern_result = @@ -690,7 +738,7 @@ { str_bsd_path = IORegistryEntryCreateCFProperty( next_media, - CFSTR( kIOBSDName ), + CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 ); if( str_bsd_path == NULL ) @@ -720,25 +768,6 @@ 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++ ) { @@ -770,29 +799,29 @@ - (IBAction) TitlePopUpChanged: (id) sender { HBTitle * title = (HBTitle*) - fTitleList->ItemAt( [fTitlePopUp indexOfSelectedItem] ); + HBListItemAt( fTitleList, [fTitlePopUp indexOfSelectedItem] ); [fLanguagePopUp removeAllItems]; [fSecondaryLanguagePopUp removeAllItems]; HBAudio * audio; - for( uint32_t i = 0; i < title->fAudioList->CountItems(); i++ ) + for( int i = 0; i < HBListCountItems( title->audioList ); i++ ) { - audio = (HBAudio*) title->fAudioList->ItemAt( i ); + audio = (HBAudio*) HBListItemAt( title->audioList, i ); /* We cannot use NSPopUpButton's addItemWithTitle because it checks for duplicate entries */ [[fLanguagePopUp menu] addItemWithTitle: - [NSString stringWithCString: audio->fDescription] + [NSString stringWithCString: audio->language] action: nil keyEquivalent: @""]; [[fSecondaryLanguagePopUp menu] addItemWithTitle: - [NSString stringWithCString: audio->fDescription] + [NSString stringWithCString: audio->language] action: nil keyEquivalent: @""]; } [fSecondaryLanguagePopUp addItemWithTitle: @"None"]; [fSecondaryLanguagePopUp selectItemWithTitle: @"None"]; [fSecondaryLanguagePopUp setEnabled: - ( title->fAudioList->CountItems() > 1 )]; + ( HBListCountItems( title->audioList ) > 1 )]; [fTargetSizeField SetHBTitle: title]; if( [fVideoMatrix selectedRow] ) @@ -801,6 +830,20 @@ } } +- (IBAction) VideoCodecPopUpChanged: (id) sender +{ + if( [[fVideoCodecPopUp titleOfSelectedItem] + compare: @"MPEG-4 (Ffmpeg)"] == NSOrderedSame ) + { + [fTwoPassCheck setEnabled: YES]; + } + else + { + [fTwoPassCheck setState: NSOffState]; + [fTwoPassCheck setEnabled: NO]; + } +} + - (IBAction) AudioPopUpChanged: (id) sender { if( [fVideoMatrix selectedRow] ) diff --git a/macosx/English.lproj/InfoPlist.strings b/macosx/English.lproj/InfoPlist.strings Binary files differindex 7690c78ef..9a0f313a7 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 38429950c..c9539b9d2 100644 --- a/macosx/English.lproj/MainMenu.nib/classes.nib +++ b/macosx/English.lproj/MainMenu.nib/classes.nib @@ -18,6 +18,7 @@ Suspend = id; TitlePopUpChanged = id; UpdatePicture = id; + VideoCodecPopUpChanged = id; VideoMatrixChanged = id; }; CLASS = HBController; @@ -40,8 +41,11 @@ fLanguagePopUp = NSPopUpButton; fLeftField = NSTextField; fLeftStepper = NSStepper; + fNextButton = NSButton; + fOpenGLCheck = NSButton; fPictureGLView = HBPictureGLView; fPicturePanel = NSPanel; + fPreviousButton = NSButton; fRightField = NSTextField; fRightStepper = NSStepper; fRipButton = NSButton; diff --git a/macosx/English.lproj/MainMenu.nib/info.nib b/macosx/English.lproj/MainMenu.nib/info.nib index af41a1429..96ab6e7ce 100644 --- a/macosx/English.lproj/MainMenu.nib/info.nib +++ b/macosx/English.lproj/MainMenu.nib/info.nib @@ -3,31 +3,31 @@ <plist version="1.0"> <dict> <key>IBDocumentLocation</key> - <string>29 16 381 380 0 0 1440 878 </string> + <string>25 188 381 380 0 0 1440 878 </string> <key>IBEditorPositions</key> <dict> <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> + <string>510 481 420 244 0 0 1440 878 </string> <key>583</key> - <string>648 516 144 171 0 0 1440 878 </string> + <string>648 517 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> + <string>349.0</string> <key>IBOpenObjects</key> <array> - <integer>583</integer> - <integer>21</integer> - <integer>589</integer> - <integer>365</integer> + <integer>556</integer> <integer>434</integer> <integer>29</integer> - <integer>556</integer> + <integer>589</integer> + <integer>21</integer> + <integer>583</integer> + <integer>365</integer> </array> <key>IBSystem Version</key> - <string>6R73</string> + <string>7B85</string> </dict> </plist> diff --git a/macosx/English.lproj/MainMenu.nib/objects.nib b/macosx/English.lproj/MainMenu.nib/objects.nib Binary files differindex 9fe323510..1e6996ef4 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 2cc6e1054..8c918d283 100644 --- a/macosx/HandBrake.pbproj/project.pbxproj +++ b/macosx/HandBrake.pbproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 38; + objectVersion = 39; objects = { 080E96DCFE201CFB7F000001 = { fileRef = 29B97318FDCFA39411CA2CEA; @@ -23,6 +23,7 @@ isa = PBXGroup; name = Classes; refType = 4; + sourceTree = "<group>"; }; 089C165CFE840E0CC02AAC07 = { children = ( @@ -31,13 +32,16 @@ isa = PBXVariantGroup; name = InfoPlist.strings; refType = 4; + sourceTree = "<group>"; }; 089C165DFE840E0CC02AAC07 = { + expectedFileType = text.plist.strings; fileEncoding = 10; isa = PBXFileReference; name = English; path = English.lproj/InfoPlist.strings; refType = 4; + sourceTree = "<group>"; }; 089C165EFE840E0CC02AAC07 = { fileRef = 089C165CFE840E0CC02AAC07; @@ -64,12 +68,16 @@ isa = PBXGroup; name = "Linked Frameworks"; refType = 4; + sourceTree = "<group>"; }; 1058C7A1FEA54F0111CA2CBB = { + expectedFileType = wrapper.framework; + fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; refType = 0; + sourceTree = "<absolute>"; }; 1058C7A2FEA54F0111CA2CBB = { children = ( @@ -79,6 +87,7 @@ isa = PBXGroup; name = "Other Frameworks"; refType = 4; + sourceTree = "<group>"; }; 1058C7A3FEA54F0111CA2CBB = { fileRef = 1058C7A1FEA54F0111CA2CBB; @@ -97,9 +106,12 @@ //173 //174 17587328FF379C6511CA2CBB = { + expectedFileType = wrapper.application; + fallbackIsa = PBXFileReference; isa = PBXApplicationReference; path = HandBrake.app; refType = 3; + sourceTree = BUILT_PRODUCTS_DIR; }; //170 //171 @@ -118,6 +130,7 @@ isa = PBXGroup; name = Products; refType = 4; + sourceTree = "<group>"; }; //190 //191 @@ -130,6 +143,10 @@ //293 //294 29B97313FDCFA39411CA2CEA = { + buildSettings = { + MACOSX_DEPLOYMENT_TARGET = 10.2; + SDKROOT = /Developer/SDKs/MacOSX10.2.7.sdk; + }; buildStyles = ( 4A9504CCFFE6A4B311CA0CBA, 4A9504CDFFE6A4B311CA0CBA, @@ -154,23 +171,26 @@ name = HandBrake; path = ""; refType = 4; + sourceTree = "<group>"; }; 29B97315FDCFA39411CA2CEA = { children = ( 29B97316FDCFA39411CA2CEA, - 4D358C040534AB8100D654EB, - 4D929FEB0527903D00A80101, + 4DFDC318054AC84C00151618, ); isa = PBXGroup; name = "Other Sources"; path = ""; refType = 4; + sourceTree = "<group>"; }; 29B97316FDCFA39411CA2CEA = { + expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; path = main.mm; refType = 4; + sourceTree = "<group>"; }; 29B97317FDCFA39411CA2CEA = { children = ( @@ -183,6 +203,7 @@ 4D69F5CC0527944A00A80101, 4D69F5CD0527944A00A80101, 4D69F5CE0527944A00A80101, + 4DDEF3B905474DCC002904DE, 4D118405053054CD00C39CA9, 089C165CFE840E0CC02AAC07, ); @@ -190,6 +211,7 @@ name = Resources; path = ""; refType = 4; + sourceTree = "<group>"; }; 29B97318FDCFA39411CA2CEA = { children = ( @@ -199,12 +221,15 @@ name = MainMenu.nib; path = ""; refType = 4; + sourceTree = "<group>"; }; 29B97319FDCFA39411CA2CEA = { + expectedFileType = wrapper.nib; isa = PBXFileReference; name = English; path = English.lproj/MainMenu.nib; refType = 4; + sourceTree = "<group>"; }; 29B97323FDCFA39411CA2CEA = { children = ( @@ -215,18 +240,25 @@ name = Frameworks; path = ""; refType = 4; + sourceTree = "<group>"; }; 29B97324FDCFA39411CA2CEA = { + expectedFileType = wrapper.framework; + fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; refType = 0; + sourceTree = "<absolute>"; }; 29B97325FDCFA39411CA2CEA = { + expectedFileType = wrapper.framework; + fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; refType = 0; + sourceTree = "<absolute>"; }; 29B97326FDCFA39411CA2CEA = { buildPhases = ( @@ -263,7 +295,7 @@ <key>CFBundleExecutable</key> <string>HandBrake</string> <key>CFBundleGetInfoString</key> - <string>HandBrake 0.4.1 - By Eric Petit <[email protected]></string> + <string>HandBrake 0.5 - By Eric Petit <[email protected]></string> <key>CFBundleIconFile</key> <string>HandBrake.icns</string> <key>CFBundleIdentifier</key> @@ -275,11 +307,11 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>0.4.1</string> + <string>0.5</string> <key>CFBundleSignature</key> <string>HB##</string> <key>CFBundleVersion</key> - <string>0.4.1</string> + <string>0.5</string> <key>NSMainNibFile</key> <string>MainMenu</string> <key>NSPrincipalClass</key> @@ -291,11 +323,10 @@ 29B97327FDCFA39411CA2CEA = { buildActionMask = 2147483647; files = ( - 4D929FEC0527903D00A80101, 4D6615EA05288C2300A80101, 4D857591052B78E300C39CA9, 4D358C020534A91300D654EB, - 4D358C050534AB8100D654EB, + 4DFDC319054AC84C00151618, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -343,6 +374,7 @@ 4D69F5D50527944A00A80101, 4DEB2025052B055F00C39CA9, 4DDE9725052B7B2B00C39CA9, + 4DDEF3BA05474DCC002904DE, ); isa = PBXFrameworksBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -362,7 +394,12 @@ ); buildSettings = { COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; OPTIMIZATION_CFLAGS = "-O0"; + ZERO_LINK = YES; }; isa = PBXBuildStyle; name = Development; @@ -372,6 +409,8 @@ ); buildSettings = { COPY_PHASE_STRIP = YES; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + ZERO_LINK = NO; }; isa = PBXBuildStyle; name = Deployment; @@ -387,9 +426,11 @@ //4D3 //4D4 4D118405053054CD00C39CA9 = { + expectedFileType = image.icns; isa = PBXFileReference; path = HandBrake.icns; refType = 4; + sourceTree = "<group>"; }; 4D118406053054CD00C39CA9 = { fileRef = 4D118405053054CD00C39CA9; @@ -398,16 +439,20 @@ }; }; 4D358C000534A91300D654EB = { + expectedFileType = sourcecode.c.h; fileEncoding = 30; isa = PBXFileReference; path = TargetSizeField.h; refType = 4; + sourceTree = "<group>"; }; 4D358C010534A91300D654EB = { + expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; path = TargetSizeField.mm; refType = 4; + sourceTree = "<group>"; }; 4D358C020534A91300D654EB = { fileRef = 4D358C000534A91300D654EB; @@ -421,19 +466,6 @@ 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; @@ -441,46 +473,60 @@ }; }; 4D69F5C80527944A00A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = liba52.a; path = /usr/local/lib/liba52.a; refType = 0; + sourceTree = "<absolute>"; }; 4D69F5C90527944A00A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = libavcodec.a; path = /usr/local/lib/libavcodec.a; refType = 0; + sourceTree = "<absolute>"; }; 4D69F5CA0527944A00A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = libdvdcss.a; path = /usr/local/lib/libdvdcss.a; refType = 0; + sourceTree = "<absolute>"; }; 4D69F5CB0527944A00A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = libdvdplay.a; path = /usr/local/lib/libdvdplay.a; refType = 0; + sourceTree = "<absolute>"; }; 4D69F5CC0527944A00A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = libdvdread.a; path = /usr/local/lib/libdvdread.a; refType = 0; + sourceTree = "<absolute>"; }; 4D69F5CD0527944A00A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = libmp3lame.a; path = /usr/local/lib/libmp3lame.a; refType = 0; + sourceTree = "<absolute>"; }; 4D69F5CE0527944A00A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = libmpeg2.a; path = /usr/local/lib/libmpeg2.a; refType = 0; + sourceTree = "<absolute>"; }; 4D69F5CF0527944A00A80101 = { fileRef = 4D69F5C80527944A00A80101; @@ -525,16 +571,20 @@ }; }; 4D85758E052B78E300C39CA9 = { + expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; path = PictureGLView.mm; refType = 4; + sourceTree = "<group>"; }; 4D85758F052B78E300C39CA9 = { + expectedFileType = sourcecode.c.h; fileEncoding = 30; isa = PBXFileReference; path = PictureGLView.h; refType = 4; + sourceTree = "<group>"; }; 4D857590052B78E300C39CA9 = { fileRef = 4D85758E052B78E300C39CA9; @@ -548,24 +598,13 @@ settings = { }; }; - 4D929FEB0527903D00A80101 = { - fileEncoding = 30; - isa = PBXFileReference; - name = Manager.h; - path = ../core/Manager.h; - refType = 4; - }; - 4D929FEC0527903D00A80101 = { - fileRef = 4D929FEB0527903D00A80101; - isa = PBXBuildFile; - settings = { - }; - }; 4D929FED0527907200A80101 = { + expectedFileType = archive.ar; isa = PBXFileReference; name = libhb.a; path = ../core/libhb.a; refType = 4; + sourceTree = "<group>"; }; 4D929FEE0527907200A80101 = { fileRef = 4D929FED0527907200A80101; @@ -574,10 +613,13 @@ }; }; 4DDE9724052B7B2B00C39CA9 = { + expectedFileType = wrapper.framework; + fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; name = OpenGL.framework; path = /System/Library/Frameworks/OpenGL.framework; refType = 0; + sourceTree = "<absolute>"; }; 4DDE9725052B7B2B00C39CA9 = { fileRef = 4DDE9724052B7B2B00C39CA9; @@ -585,11 +627,28 @@ settings = { }; }; + 4DDEF3B905474DCC002904DE = { + expectedFileType = archive.ar; + isa = PBXFileReference; + name = libxvidcore.a; + path = /usr/local/lib/libxvidcore.a; + refType = 0; + sourceTree = "<absolute>"; + }; + 4DDEF3BA05474DCC002904DE = { + fileRef = 4DDEF3B905474DCC002904DE; + isa = PBXBuildFile; + settings = { + }; + }; 4DEB2024052B055F00C39CA9 = { + expectedFileType = wrapper.framework; + fallbackIsa = PBXFileReference; isa = PBXFrameworkReference; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; refType = 0; + sourceTree = "<absolute>"; }; 4DEB2025052B055F00C39CA9 = { fileRef = 4DEB2024052B055F00C39CA9; @@ -598,16 +657,20 @@ }; }; 4DF3C8CB052889CD00A80101 = { + expectedFileType = sourcecode.c.h; fileEncoding = 30; isa = PBXFileReference; path = Controller.h; refType = 4; + sourceTree = "<group>"; }; 4DF3C8CC052889CD00A80101 = { + expectedFileType = sourcecode.cpp.objcpp; fileEncoding = 30; isa = PBXFileReference; path = Controller.mm; refType = 4; + sourceTree = "<group>"; }; 4DF3C8CE052889CD00A80101 = { fileRef = 4DF3C8CC052889CD00A80101; @@ -615,6 +678,21 @@ settings = { }; }; + 4DFDC318054AC84C00151618 = { + expectedFileType = sourcecode.c.h; + fileEncoding = 30; + isa = PBXFileReference; + name = HandBrake.h; + path = ../core/HandBrake.h; + refType = 4; + sourceTree = "<group>"; + }; + 4DFDC319054AC84C00151618 = { + fileRef = 4DFDC318054AC84C00151618; + isa = PBXBuildFile; + settings = { + }; + }; }; rootObject = 29B97313FDCFA39411CA2CEA; } diff --git a/macosx/PictureGLView.h b/macosx/PictureGLView.h index 06e5a16e1..c558c3c0f 100644 --- a/macosx/PictureGLView.h +++ b/macosx/PictureGLView.h @@ -1,20 +1,34 @@ -/* PictureGLView */ +/* $Id: PictureGLView.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ #include <Cocoa/Cocoa.h> -#include "Manager.h" +#include "HandBrake.h" + +#define HB_ANIMATE_NONE 0 +#define HB_ANIMATE_LEFT 1 +#define HB_ANIMATE_RIGHT 2 @interface HBPictureGLView : NSOpenGLView { - HBManager * fManager; + HBHandle * fHandle; HBTitle * fTitle; uint8_t * fPicture; + uint8_t * fOldPicture; } -- (void) SetManager: (HBManager*) manager; +- (id) initWithFrame: (NSRect) frame; +- (void) reshape; +- (void) drawRect: (NSRect) rect; +- (void) drawAnimation: (int) how; + +- (void) SetHandle: (HBHandle*) handle; - (void) SetTitle: (HBTitle*) title; -- (void) ShowPicture: (int) picture; +- (void) ShowPicture: (int) index animate: (int) how; @end diff --git a/macosx/PictureGLView.mm b/macosx/PictureGLView.mm index 79103f6b6..8df19907b 100644 --- a/macosx/PictureGLView.mm +++ b/macosx/PictureGLView.mm @@ -1,68 +1,153 @@ +/* $Id: PictureGLView.mm,v 1.3 2003/11/03 22:01:13 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + #include <OpenGL/gl.h> +#include <math.h> #include "PictureGLView.h" +#define PROUT 2.5 + +/* XXX This file needs some serious cleaning XXX */ + +GLuint texture[2]; +float rotation; +float translation; +uint8_t * truc; + @implementation HBPictureGLView -- (void) SetManager: (HBManager*) manager +- (void) SetHandle: (HBHandle*) handle { - fManager = manager; + fHandle = handle; } - (void) SetTitle: (HBTitle*) title { fTitle = title; - + /* This is needed as the view's size may have changed */ [self clearGLContext]; [self openGLContext]; } -- (void) ShowPicture: (int) index +- (void) ShowPicture: (int) index animate: (int) how { + if( fOldPicture ) free( fOldPicture ); + fOldPicture = fPicture; + /* Get the picture */ - uint8_t * tmp = fManager->GetPreview( fTitle, index ); + uint8_t * tmp = HBGetPreview( fHandle, fTitle, index ); /* Make it be upside-down */ - if( fPicture ) free( fPicture ); - fPicture = (uint8_t*) malloc( 4 * ( fTitle->fOutWidthMax + 2 ) * - ( fTitle->fOutHeightMax + 2 ) ); - for( uint32_t i = 0; i < fTitle->fOutHeightMax + 2; i++ ) + fPicture = (uint8_t*) malloc( 4 * ( fTitle->outWidthMax + 2 ) * + ( fTitle->outHeightMax + 2 ) ); + uint8_t * in = tmp; + uint8_t * out = fPicture + + 4 * ( fTitle->outWidthMax + 2 ) * ( fTitle->outHeightMax + 1 ); + for( int i = 0; i < fTitle->outHeightMax + 2; i++ ) { - memcpy( fPicture + 4 * ( fTitle->fOutWidthMax + 2 ) * i, - tmp + 4 * ( fTitle->fOutWidthMax + 2 ) * - ( fTitle->fOutHeightMax + 1 - i ), - 4 * ( fTitle->fOutWidthMax + 2 ) ); + memcpy( out, in, 4 * ( fTitle->outWidthMax + 2 ) ); + in += 4 * ( fTitle->outWidthMax + 2 ); + out -= 4 * ( fTitle->outWidthMax + 2 ); } free( tmp ); - /* Grrr - should find a way to give ARGB to OpenGL */ - uint8_t r, g, b, a; - for( uint32_t i = 0; i < fTitle->fOutHeightMax + 2; i++ ) + /* ARGB -> RGBA */ + uint32_t * p = (uint32_t*) fPicture; + for( int i = 0; + i < ( fTitle->outHeightMax + 2 ) * ( fTitle->outWidthMax + 2 ); + i++ ) + { + *(p++) = ( ( (*p) & 0xff000000 ) >> 24 ) | + ( ( (*p) & 0x00ff0000 ) << 8 ) | + ( ( (*p) & 0x0000ff00 ) << 8 ) | + ( ( (*p) & 0x000000ff ) << 8 ); + } + + if( how == HB_ANIMATE_NONE ) + { + [self drawRect: [self bounds]]; + return; + } + + in = fOldPicture; + out = truc; + for( int i = 0; i < fTitle->outHeightMax + 2; i++ ) + { + memcpy( out, in, ( fTitle->outWidthMax + 2 ) * 4 ); + in += ( fTitle->outWidthMax + 2 ) * 4; + out += 1024 * 4; + } + glBindTexture( GL_TEXTURE_2D, texture[0] ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 1024, + 1024, 0, GL_RGBA, + GL_UNSIGNED_BYTE, truc ); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + + in = fPicture; + out = truc; + for( int i = 0; i < fTitle->outHeightMax + 2; i++ ) { - for( uint32_t j = 0; j < fTitle->fOutWidthMax + 2; j++ ) + memcpy( out, in, ( fTitle->outWidthMax + 2 ) * 4 ); + in += ( fTitle->outWidthMax + 2 ) * 4; + out += 1024 * 4; + } + glBindTexture( GL_TEXTURE_2D, texture[1] ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 1024, + 1024, 0, GL_RGBA, + GL_UNSIGNED_BYTE, truc ); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + + glEnable( GL_TEXTURE_2D ); + glShadeModel( GL_SMOOTH ); + glClearColor( 0.0f, 0.0f, 0.0f, 0.5f ); + glClearDepth( 1.0f ); + glEnable( GL_DEPTH_TEST ); + glDepthFunc( GL_LEQUAL ); + glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); + +#define ANIMATION_TIME 500000 + + rotation = 0.0; + float w = ( how == HB_ANIMATE_LEFT ) ? 1.0 : -1.0; + uint64_t date; + int64_t wait; + for( ;; ) + { + date = HBGetDate(); + translation = - PROUT - cos( rotation * M_PI / 180 ) * + ( 1 + w * tan( rotation * M_PI / 180 ) ); + + [self drawAnimation: how]; + + rotation += w; + if( w * rotation >= 90.0 ) + { + break; + } + + wait = ANIMATION_TIME / 90 - ( HBGetDate() - date ); + if( wait > 0 ) { - a = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)]; - r = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+1]; - g = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+2]; - b = fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+3]; - - fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)] = r; - fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+1] = g; - fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+2] = b; - fPicture[4*(i*(fTitle->fOutWidthMax+2)+j)+3] = a; + HBSnooze( wait ); } } - [self setNeedsDisplay: YES]; + [self drawRect: [self bounds]]; } -/* Override NSView's initWithFrame: to specify our pixel format */ - (id) initWithFrame: (NSRect) frame { - fManager = NULL; - fTitle = NULL; - fPicture = NULL; + fHandle = NULL; + fTitle = NULL; + fPicture = NULL; + fOldPicture = NULL; GLuint attribs[] = { @@ -81,34 +166,109 @@ NSOpenGLPixelFormat * fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes: (NSOpenGLPixelFormatAttribute*) attribs]; - if( !fmt ) + self = [super initWithFrame:frame pixelFormat: [fmt autorelease]]; + + if( !self ) { - fprintf( stderr, "Sarass\n" ); + return NULL; } - return self = [super initWithFrame:frame pixelFormat: - [fmt autorelease]]; + [[self openGLContext] makeCurrentContext]; + [self reshape]; + + glGenTextures( 2, texture ); + truc = (uint8_t*) malloc( 1024*1024*4 ); + + return self; +} + +/* + * Resize ourself + */ +- (void) reshape +{ + NSRect bounds; + + [[self openGLContext] update]; + bounds = [self bounds]; + glViewport( 0, 0, (GLsizei) bounds.size.width, + (GLsizei) bounds.size.height ); +} + +- (void) drawAnimation: (int) how +{ + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); + glMatrixMode( GL_PROJECTION ); + glLoadIdentity(); + glFrustum( -1.0, 1.0, -1.0, 1.0, PROUT, 20.0 ); + glMatrixMode( GL_MODELVIEW ); + glLoadIdentity(); + glTranslatef( 0.0, 0.0, translation ); + glRotatef( rotation, 0.0, 1.0, 0.0 ); + + glEnable( GL_POLYGON_SMOOTH ); + glHint( GL_POLYGON_SMOOTH_HINT, GL_NICEST ); + + glBindTexture( GL_TEXTURE_2D, texture[0] ); + + glBegin( GL_QUADS ); + glTexCoord2f( 0.0, 0.0 ); + glVertex3f( -1.0, -1.0, 1.0 ); + glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, 0.0 ); + glVertex3f( 1.0, -1.0, 1.0 ); + glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, + ( 2.0 + fTitle->outHeightMax ) / 1024 ); + glVertex3f( 1.0, 1.0, 1.0 ); + glTexCoord2f( 0.0, ( 2.0 + fTitle->outHeightMax ) / 1024 ); + glVertex3f( -1.0, 1.0, 1.0 ); + glEnd(); + + glBindTexture( GL_TEXTURE_2D, texture[1] ); + + glBegin( GL_QUADS ); + if( how == HB_ANIMATE_RIGHT ) + { + glTexCoord2f( 0.0, 0.0 ); + glVertex3f( 1.0, -1.0, 1.0 ); + glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, 0.0 ); + glVertex3f( 1.0, -1.0, -1.0 ); + glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, + ( 2.0 + fTitle->outHeightMax ) / 1024 ); + glVertex3f( 1.0, 1.0, -1.0 ); + glTexCoord2f( 0.0, ( 2.0 + fTitle->outHeightMax ) / 1024 ); + glVertex3f( 1.0, 1.0, 1.0 ); + } + else + { + glTexCoord2f( 0.0, 0.0 ); + glVertex3f( -1.0, -1.0, -1.0 ); + glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, 0.0 ); + glVertex3f( -1.0, -1.0, 1.0 ); + glTexCoord2f( ( 2.0 + fTitle->outWidthMax ) / 1024, + ( 2.0 + fTitle->outHeightMax ) / 1024 ); + glVertex3f( -1.0, 1.0, 1.0 ); + glTexCoord2f( 0.0, ( 2.0 + fTitle->outHeightMax ) / 1024 ); + glVertex3f( -1.0, 1.0, -1.0 ); + } + glEnd(); + + [[self openGLContext] flushBuffer]; } -/* Override the view's drawRect: to draw our GL content */ - (void) drawRect: (NSRect) rect { - glViewport( 0, 0, (GLsizei) rect.size.width, - (GLsizei) rect.size.height ); + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - /* Black background */ - glClearColor( 0, 0, 0, 0 ); - glClear( GL_COLOR_BUFFER_BIT ); + if( !fPicture ) + { + return; + } - /* Show it */ - if( fPicture ) - { - glDrawPixels( fTitle->fOutWidthMax + 2, - fTitle->fOutHeightMax + 2, GL_RGBA, - GL_UNSIGNED_BYTE, fPicture ); - } + glDrawPixels( fTitle->outWidthMax + 2, + fTitle->outHeightMax + 2, GL_RGBA, + GL_UNSIGNED_BYTE, fPicture ); - [[self openGLContext] flushBuffer]; + [[self openGLContext] flushBuffer]; } @end diff --git a/macosx/TargetSizeField.h b/macosx/TargetSizeField.h index 12224cae7..6bc4a716f 100644 --- a/macosx/TargetSizeField.h +++ b/macosx/TargetSizeField.h @@ -1,12 +1,12 @@ -/* $Id: TargetSizeField.h,v 1.2 2003/10/09 23:33:36 titer Exp $ +/* $Id: TargetSizeField.h,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include <Cocoa/Cocoa.h> -#include "Common.h" +#include "HandBrake.h" @interface HBTargetSizeField : NSTextField diff --git a/macosx/TargetSizeField.mm b/macosx/TargetSizeField.mm index 0c43701fb..bde9f0ec2 100644 --- a/macosx/TargetSizeField.mm +++ b/macosx/TargetSizeField.mm @@ -1,7 +1,7 @@ -/* $Id: TargetSizeField.mm,v 1.4 2003/10/09 23:33:36 titer Exp $ +/* $Id: TargetSizeField.mm,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #include "TargetSizeField.h" @@ -41,14 +41,14 @@ /* Video chunk headers (8 bytes / frame) and index (16 bytes / frame) */ - available -= 24 * fTitle->fLength * fTitle->fRate / fTitle->fScale; + available -= 24 * fTitle->length * fTitle->rate / fTitle->rateBase; /* Audio tracks */ available -= ( ( [[fSecondaryLanguagePopUp titleOfSelectedItem] compare: @"None"] == NSOrderedSame ) ? 1 : 2 ) * - ( fTitle->fLength * + ( fTitle->length * [[fAudioBitratePopUp titleOfSelectedItem] intValue] * - 128 + 24 * fTitle->fLength * 44100 / 1152 ); + 128 + 24 * fTitle->length * 44100 / 1152 ); if( available < 0 ) { @@ -57,7 +57,7 @@ else { [fBitrateField setIntValue: - available / ( 128 * fTitle->fLength )]; + available / ( 128 * fTitle->length )]; } } diff --git a/macosx/main.mm b/macosx/main.mm index 56aa102fa..bd649f8ba 100644 --- a/macosx/main.mm +++ b/macosx/main.mm @@ -1,7 +1,7 @@ -/* $Id: main.mm,v 1.5 2003/09/30 14:38:15 titer Exp $ +/* $Id: main.mm,v 1.1.1.1 2003/11/03 12:03:51 titer Exp $ This file is part of the HandBrake source code. - Homepage: <http://beos.titer.org/handbrake/>. + Homepage: <http://handbrake.m0k.org/>. It may be used under the terms of the GNU General Public License. */ #import <Cocoa/Cocoa.h> diff --git a/test/Test.cpp b/test/Test.cpp deleted file mode 100644 index 4567f74b6..000000000 --- a/test/Test.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/* $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/>. - It may be used under the terms of the GNU General Public License. */ - -#include <signal.h> - -#include "Manager.h" - -volatile bool die; - -void SigHandler( int signal ) -{ - die = true; -} - -int main( int argc, char ** argv ) -{ - die = false; - - /* Exit ASAP on Ctrl-C */ - signal( SIGINT, SigHandler ); - - /* Default values */ - bool debug = false; - char * device = NULL; - char * outputFile = NULL; - int titleIdx = 1; - int audio1Idx = 1; - int audio2Idx = 0; - bool twoPass = false; - bool deinterlace = false; - int width = 0; - int topCrop = 0; - 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:a:b:piw:j:k:l:m:c:e:f:" ) ) != -1 ) - { - switch( c ) - { - case 'v': - debug = true; - break; - - case 'd': - device = strdup( optarg ); - break; - - case 'o': - outputFile = strdup( optarg ); - break; - - case 't': - titleIdx = atoi( optarg ); - break; - - case 'a': - audio1Idx = atoi( optarg ); - break; - - case 'b': - audio2Idx = atoi( optarg ); - break; - - case 'p': - twoPass = true; - break; - - case 'i': - deinterlace = true; - break; - - case 'w': - width = atoi( optarg ); - break; - - case 'j': - topCrop = atoi( optarg ); - break; - - case 'k': - bottomCrop = atoi( optarg ); - break; - - case 'l': - leftCrop = atoi( optarg ); - break; - - case 'm': - rightCrop = atoi( optarg ); - break; - - case 'c': - cpuCount = atoi( optarg ); - break; - - case 'e': - vBitrate = atoi( optarg ); - break; - - case 'f': - aBitrate = atoi( optarg ); - break; - - default: - break; - } - } - - /* Check parsed options */ - if( !device || !outputFile ) - { - fprintf( stderr, - "Syntax: HBTest [options] -d <device> -o <file>\n" - "Possible options are :\n" - " -v verbose output\n" - " -t <value> select a title (default is 1)\n" - " -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, cpuCount ); - - /* Tell the manager to scan the specified volume */ - manager->ScanVolumes( device ); - - HBStatus status; - while( !die ) - { - if( !manager->NeedUpdate() ) - { - Snooze( 10000 ); - continue; - } - - status = manager->GetStatus(); - - switch( status.fMode ) - { - case HB_MODE_UNDEF: - break; - - case HB_MODE_SCANNING: - if( !status.fScannedTitle ) - { - fprintf( stderr, "Scanning %s\n", - status.fScannedVolume ); - } - else - { - fprintf( stderr, "Scanning %s, title %d\n", - status.fScannedVolume, - status.fScannedTitle ); - } - break; - - case HB_MODE_READY_TO_RIP: - { - /* Find the title */ - HBTitle * title = NULL; - for( uint32_t i = 0; i < status.fTitleList->CountItems(); i++ ) - { - title = (HBTitle*) status.fTitleList->ItemAt( i ); - if( title->fIndex == titleIdx ) - { - break; - } - else - { - title = NULL; - } - } - - if( !title ) - { - fprintf( stderr, "Error: unvalid title. Possible " - "choices are: " ); - for( uint32_t i = 0; - i < status.fTitleList->CountItems(); i++ ) - { - title = (HBTitle*) status.fTitleList->ItemAt( i ); - fprintf( stderr, "%d%s", title->fIndex, - ( i == status.fTitleList->CountItems() - 1 ) - ? ".\n" : ", " ); - } - die = true; - break; - } - title->fTwoPass = twoPass; - title->fDeinterlace = deinterlace; - if( width ) title->fOutWidth = width; - title->fTopCrop = topCrop; - title->fBottomCrop = bottomCrop; - title->fLeftCrop = leftCrop; - title->fRightCrop = rightCrop; - title->fBitrate = vBitrate; - - 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, audio1, audio2, outputFile ); - break; - } - - case HB_MODE_ENCODING: - fprintf( stderr, "Progress = %.2f %%, %.2f fps " - "(%02d:%02d:%02d remaining)\n", - 100 * status.fPosition, status.fFrameRate, - status.fRemainingTime / 3600, - ( status.fRemainingTime % 3600 ) / 60, - status.fRemainingTime % 60 ); - break; - - case HB_MODE_DONE: - fprintf( stderr, "Done\n" ); - die = true; - break; - - case HB_MODE_CANCELED: - fprintf( stderr, "Canceled\n" ); - die = true; - break; - - case HB_MODE_ERROR: - fprintf( stderr, "Error\n" ); - die = true; - break; - - default: - break; - } - } - - delete manager; - - if( device ) free( device ); - if( outputFile ) free( outputFile ); - - return 0; -} - diff --git a/test/test.c b/test/test.c new file mode 100644 index 000000000..ec576cbb3 --- /dev/null +++ b/test/test.c @@ -0,0 +1,237 @@ +/* $Id: test.c,v 1.5 2003/11/06 13:28:07 titer Exp $ + + This file is part of the HandBrake source code. + Homepage: <http://handbrake.m0k.org/>. + It may be used under the terms of the GNU General Public License. */ + +#include <signal.h> + +#include "HandBrake.h" + +volatile int die; + +void SigHandler( int signal ) +{ + die = 1; +} + +int main( int argc, char ** argv ) +{ + int c; + HBHandle * h; + HBStatus s; + + /* Default values */ + int debug = 1; + char * device = NULL; + char * file = NULL; + int titleIdx = 1; + int audio1Idx = 1; + int audio2Idx = 0; + int twoPass = 0; + int deinterlace = 0; + int width = 0; + int topCrop = 0; + int bottomCrop = 0; + int leftCrop = 0; + int rightCrop = 0; + int cpuCount = 0; + int vBitrate = 1024; + int aBitrate = 128; + int xvid = 0; + + die = 0; + + /* Exit ASAP on Ctrl-C */ + signal( SIGINT, SigHandler ); + + /* Parse command line */ + while( ( c = getopt( argc, argv, "qd:o:t:a:b:piw:j:k:l:m:c:e:f:x" ) ) != -1 ) + { + switch( c ) + { + case 'q': + debug = 0; + break; + + case 'd': + device = strdup( optarg ); + break; + + case 'o': + file = strdup( optarg ); + break; + + case 't': + titleIdx = atoi( optarg ); + break; + + case 'a': + audio1Idx = atoi( optarg ); + break; + + case 'b': + audio2Idx = atoi( optarg ); + break; + + case 'p': + twoPass = 1; + break; + + case 'i': + deinterlace = 1; + break; + + case 'w': + width = atoi( optarg ); + break; + + case 'j': + topCrop = atoi( optarg ); + break; + + case 'k': + bottomCrop = atoi( optarg ); + break; + + case 'l': + leftCrop = atoi( optarg ); + break; + + case 'm': + rightCrop = atoi( optarg ); + break; + + case 'c': + cpuCount = atoi( optarg ); + break; + + case 'e': + vBitrate = atoi( optarg ); + break; + + case 'f': + aBitrate = atoi( optarg ); + break; + + case 'x': + xvid = 1; + break; + + default: + break; + } + } + + /* Check parsed options */ + if( !device || !file ) + { + fprintf( stderr, + "Syntax: HBTest [options] -d <device> -o <file>\n" + "Possible options are :\n" + " -q quiet 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 (default: autodetected)\n" + " -e <value> Video bitrate (default is 1024)\n" + " -f <value> Audio bitrate (default is 128)\n" + " -x Use XviD instead of Ffmpeg\n" ); + return 1; + } + + /* Create the manager thread */ + h = HBInit( debug, cpuCount ); + + while( !die ) + { + HBSnooze( 100000 ); + + if( !HBGetStatus( h, &s ) ) + continue; + + switch( s.mode ) + { + case HB_MODE_UNDEF: + /* Will never happen */ + break; + + case HB_MODE_NEED_DEVICE: + /* Feed libhb with a DVD to scan */ + HBScanDevice( h, device, titleIdx ); + break; + + case HB_MODE_SCANNING: + /* s.scannedTitle: title scanned at the moment */ + break; + + case HB_MODE_INVALID_DEVICE: + die = 1; + break; + + case HB_MODE_READY_TO_RIP: + { + HBAudio * audio1, * audio2; + HBTitle * title = HBListItemAt( s.titleList, 0 ); + + title->file = strdup( file ); + title->twoPass = twoPass; + title->deinterlace = deinterlace; + if( width ) title->outWidth = width; + title->topCrop = topCrop; + title->bottomCrop = bottomCrop; + title->leftCrop = leftCrop; + title->rightCrop = rightCrop; + title->bitrate = vBitrate; + title->codec = xvid ? HB_CODEC_XVID : HB_CODEC_FFMPEG; + + audio1 = HBListItemAt( title->audioList, + audio1Idx - 1 ); + audio2 = HBListItemAt( title->audioList, + audio2Idx - 1 ); + if( audio1 ) audio1->outBitrate = aBitrate; + if( audio2 ) audio2->outBitrate = aBitrate; + + HBStartRip( h, title, audio1, audio2 ); + break; + } + + case HB_MODE_ENCODING: + /* s.position : current progress (0.0->1.0) + s.frameRate : average framerate + s.remainingTime: ... (in seconds) */ + break; + + case HB_MODE_DONE: + die = 1; + break; + + case HB_MODE_CANCELED: + die = 1; + break; + + case HB_MODE_ERROR: + /* s.error: error code */ + die = 1; + break; + + default: + break; + } + } + + HBClose( &h ); + + if( device ) free( device ); + if( file ) free( file ); + + return 0; +} + |