summaryrefslogtreecommitdiffstats
path: root/core/Scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/Scan.c')
-rw-r--r--core/Scan.c254
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 )