/* $Id: Utils.c,v 1.20 2004/05/12 17:21:24 titer Exp $
This file is part of the HandBrake source code.
Homepage: .
It may be used under the terms of the GNU General Public License. */
#include
#include
#include
#ifdef HB_CYGWIN
# include
#endif
#include "Utils.h"
#include "Fifo.h"
#ifdef HB_CYGWIN
int gettimeofday( struct timeval * tv, struct timezone * tz )
{
tv->tv_sec = 0;
tv->tv_usec = 0;
return 0;
}
void bcopy( const void * src, void * dest, size_t n )
{
memcpy( dest, src, n );
}
#endif
struct HBList
{
void ** items;
int allocItems;
int nbItems;
};
void HBSnooze( int time )
{
#if defined( HB_BEOS )
snooze( time );
#elif defined( HB_MACOSX ) || defined( HB_LINUX )
usleep( time );
#elif defined( HB_CYGWIN )
Sleep( time / 1000 );
#endif
}
void HBLog( char * log, ... )
{
char string[80];
time_t _now;
struct tm * now;
va_list args;
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 );
vsnprintf( string + 11, 67, log, args );
va_end( args );
/* Add the end of line */
strcat( string, "\n" );
/* Print it */
fprintf( stderr, "%s", string );
}
uint64_t HBGetDate()
{
#ifndef HB_CYGWIN
struct timeval tv;
gettimeofday( &tv, NULL );
return( (uint64_t) tv.tv_sec * 1000000 + (uint64_t) tv.tv_usec );
#else
return( 1000 * GetTickCount() );
#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], d[pos+1], d[pos+2], 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 )
{
int streamId;
int PES_packet_length;
int PES_packet_end;
int PES_header_d_length;
int 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 &&
( streamId & 0xC0 ) != 0xC0 )
{
/* 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 )
{
streamId |= ( d[pos] << 8 );
if( ( streamId & 0xF0FF ) == 0x80BD )
{
/* A52 */
pos += 4;
}
else if( ( streamId & 0xF0FF ) == 0xA0BD )
{
/* LPCM */
pos += 1;
}
}
/* Sanity check */
if( 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;
}
#undef d
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 HBListCount( 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;
if( !( t = calloc( sizeof( HBTitle ), 1 ) ) )
{
HBLog( "HBTitleInit: calloc() failed, gonna crash" );
return NULL;
}
t->device = strdup( device );
t->title = index;
t->codec = HB_CODEC_FFMPEG;
t->mux = HB_MUX_MP4;
t->audioList = HBListInit();
t->ripAudioList = HBListInit();
t->start = -1;
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 );
HBListClose( &t->ripAudioList );
if( t->file ) free( t->file );
free( t->device );
free( t );
*_t = NULL;
}
HBAudio * HBAudioInit( int id, char * language, int codec )
{
HBAudio * a;
if( !( a = calloc( sizeof( HBAudio ), 1 ) ) )
{
HBLog( "HBAudioInit: calloc() failed, gonna crash" );
return NULL;
}
a->id = id;
a->start = -1;
a->inCodec = codec;
memset( a->language, 0, 512 );
snprintf( a->language, 511, "%s (%s)", language,
( codec == HB_CODEC_AC3 ) ? "AC3" : ( ( codec ==
HB_CODEC_LPCM ? "LPCM" : "MPEG" ) ) );
return a;
}
void HBAudioClose( HBAudio ** _a )
{
HBAudio * a = *_a;
free( a );
*_a = NULL;
}