diff options
Diffstat (limited to 'core/Scan.c')
-rw-r--r-- | core/Scan.c | 254 |
1 files changed, 162 insertions, 92 deletions
diff --git a/core/Scan.c b/core/Scan.c index 7a62a97e0..f2afd5e6c 100644 --- a/core/Scan.c +++ b/core/Scan.c @@ -1,21 +1,19 @@ -/* $Id: Scan.c,v 1.5 2003/11/09 21:28:22 titer Exp $ +/* $Id: Scan.c,v 1.14 2004/01/18 13:21:12 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 "HBInternal.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 "dvdread/ifo_types.h" +#include "dvdplay/dvdplay.h" +#include "dvdplay/info.h" +#include "dvdplay/state.h" +#include "dvdplay/nav.h" -#include <mpeg2dec/mpeg2.h> +#include "mpeg2dec/mpeg2.h" /* Local prototypes */ static void ScanThread( void * ); @@ -26,14 +24,14 @@ static char * LanguageForCode( int code ); struct HBScan { - HBHandle * handle; - char * device; - int title; - int die; - HBThread * thread; + HBHandle * handle; + char * device; + int title; + volatile int die; + HBThread * thread; }; -HBScan * HBScanInit( HBHandle * handle, char * device, int title ) +HBScan * HBScanInit( HBHandle * handle, const char * device, int title ) { HBScan * s; if( !( s = malloc( sizeof( HBScan ) ) ) ) @@ -55,7 +53,7 @@ HBScan * HBScanInit( HBHandle * handle, char * device, int title ) void HBScanClose( HBScan ** _s ) { HBScan * s = *_s; - + s->die = 1; HBThreadClose( &s->thread ); @@ -66,65 +64,77 @@ void HBScanClose( HBScan ** _s ) static void ScanThread( void * _s ) { - HBScan * s = (HBScan*) _s; - dvdplay_ptr vmg; - HBList * titleList = HBListInit(); - HBTitle * title; - int i; + 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 ); + HBListClose( &titleList ); + HBScanDone( s->handle, NULL ); return; } /* Detect titles */ - for( i = ( s->title ? s->title - 1 : 0 ); - i < ( s->title ? s->title : dvdplay_title_nr( vmg ) ); - i++ ) + i = s->title ? ( s->title - 1 ) : 0; + while( !s->die ) { - if( s->die ) + if( ( title = ScanTitle( s, vmg, i + 1 ) ) ) { - break; + HBListAdd( titleList, title ); } - - if( !( title = ScanTitle( s, vmg, i + 1 ) ) ) + if( s->title || i == dvdplay_title_nr( vmg ) - 1 ) { - continue; + break; } - - HBListAdd( titleList, title ); + i++; } HBLog( "HBScan: closing device %s", s->device ); dvdplay_close( vmg ); + if( s->die ) + { + while( ( title = HBListItemAt( titleList, 0 ) ) ) + { + HBListRemove( titleList, title ); + HBTitleClose( &title ); + } + HBListClose( &titleList ); + return; + } + + if( !HBListCount( titleList ) ) + { + HBListClose( &titleList ); + } HBScanDone( s->handle, titleList ); } static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) { - HBTitle * title; - int audio_nr, foo; + 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 ); + HBAudio * audio; + int i; + uint8_t dummy[DVD_VIDEO_LB_LEN]; + + HBScanning( s->handle, index, dvdplay_title_nr( vmg ) ); 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 ); + HBLog( "HBScan: title %d: length is %d seconds", index, + title->length ); /* Discard titles under 10 seconds */ if( title->length < 10 ) @@ -139,9 +149,8 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) for( i = 0; i < audio_nr; i++ ) { - int id; - int j; - + int id, j; + if( s->die ) { break; @@ -156,13 +165,14 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) if( ( id & 0xF0FF ) != 0x80BD ) { - HBLog( "HBScan: non-AC3 audio track detected, ignoring" ); + HBLog( "HBScan: title %d: non-AC3 audio track detected, " + "ignoring", index ); continue; } /* Check if we don't already found an track with the same id */ audio = NULL; - for( j = 0; j < HBListCountItems( title->audioList ); j++ ) + for( j = 0; j < HBListCount( title->audioList ); j++ ) { audio = (HBAudio*) HBListItemAt( title->audioList, j ); if( id == audio->id ) @@ -177,28 +187,29 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) if( audio ) { - HBLog( "HBScan: discarding duplicate track %x", id ); + HBLog( "HBScan: title %d: discarding duplicate track %x", + index, id ); continue; } - attr = dvdplay_audio_attr( vmg, j ); + attr = dvdplay_audio_attr( vmg, j ); audio = HBAudioInit( id, LanguageForCode( attr->lang_code ) ); - HBLog( "HBScan: new language (%x, %s)", id, audio->language ); + HBLog( "HBScan: title %d: new language (%x, %s)", index, id, + audio->language ); HBListAdd( title->audioList, audio ); } /* Discard titles with no audio tracks */ - if( !HBListCountItems( title->audioList ) ) + if( !HBListCount( 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 */ + /* Kludge : libdvdplay wants us to read a first block before seeking */ dvdplay_read( vmg, dummy, 1 ); - for( i = 0; i < 10; i++ ) { if( s->die ) @@ -215,6 +226,7 @@ static HBTitle * ScanTitle( HBScan * s, dvdplay_ptr vmg, int index ) } } + /* Handle ratio */ if( title->inHeight * title->aspect > title->inWidth * VOUT_ASPECT_FACTOR ) { @@ -248,8 +260,9 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, mpeg2dec_t * handle; const mpeg2_info_t * info; mpeg2_state_t state; - char fileName[1024]; - FILE * file; + char fileName[1024]; + FILE * file; + int ret = 1; HBList * esBufferList = HBListInit(); HBBuffer * psBuffer = NULL; @@ -259,43 +272,34 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, dvdplay_seek( vmg, pictureStart ); /* Init libmpeg2 */ +#ifdef HB_NOMMX + mpeg2_accel( 0 ); +#endif 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 ), + 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 ) ) + while( !HBListCount( esBufferList ) ) { psBuffer = HBBufferInit( DVD_VIDEO_LB_LEN ); if( dvdplay_read( vmg, psBuffer->data, 1 ) != 1 || @@ -303,18 +307,21 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, { HBLog( "HBScan: failed to get a valid PS " "packet" ); - CLEANUP; - return 0; + break; } if( dvdplay_position( vmg ) >= pictureEnd ) { HBLog( "HBScan: gone too far, aborting" ); - CLEANUP; - return 0; + break; } } + if( !HBListCount( esBufferList ) ) + { + break; + } + esBuffer = (HBBuffer*) HBListItemAt( esBufferList, 0 ); HBListRemove( esBufferList, esBuffer ); @@ -324,27 +331,80 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, } } + if( !esBuffer ) + { + ret = 0; + break; + } + /* 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; + if( !which ) + { + /* 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; + + title->autoTopCrop = title->inHeight / 2; + title->autoBottomCrop = title->inHeight / 2; + title->autoLeftCrop = title->inWidth / 2; + title->autoRightCrop = title->inWidth / 2; + } } else if( ( state == STATE_SLICE || state == STATE_END ) && ( info->display_fbuf ) && ( info->display_picture->flags & PIC_MASK_CODING_TYPE ) == PIC_FLAG_CODING_TYPE_I ) { +#define Y info->display_fbuf->buf[0] +#define DARK 64 + /* Detect black borders */ + int i, j; + for( i = 0; i < title->inWidth; i++ ) + { + for( j = 0; j < title->autoTopCrop; j++ ) + if( Y[ j * title->inWidth + i ] > DARK ) + { + title->autoTopCrop = j; + break; + } + for( j = 0; j < title->autoBottomCrop; j++ ) + if( Y[ ( title->inHeight - j - 1 ) * + title->inWidth + i ] > DARK ) + { + title->autoBottomCrop = j; + break; + } + } + for( i = 0; i < title->inHeight; i++ ) + { + for( j = 0; j < title->autoLeftCrop; j++ ) + if( Y[ i * title->inWidth + j ] > DARK ) + { + title->autoLeftCrop = j; + break; + } + for( j = 0; j < title->autoRightCrop; j++ ) + if( Y[ i * title->inWidth + + title->inWidth - j - 1 ] > DARK ) + { + title->autoRightCrop = j; + break; + } + } +#undef Y +#undef DARK + /* Write the raw picture to a file */ fwrite( info->display_fbuf->buf[0], title->inWidth * title->inHeight, 1, file ); @@ -358,15 +418,25 @@ static int DecodeFrame( HBScan * s, dvdplay_ptr vmg, { /* Reset libmpeg2 */ mpeg2_close( handle ); +#ifdef HB_NOMMX + mpeg2_accel( 0 ); +#endif handle = mpeg2_init(); } } - CLEANUP; - - return 1; + 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 ); -#undef CLEANUP + return ret; } static char * LanguageForCode( int code ) |