diff options
author | van <[email protected]> | 2008-03-20 05:28:36 +0000 |
---|---|---|
committer | van <[email protected]> | 2008-03-20 05:28:36 +0000 |
commit | 5265ea2db4fb71b3b894c16b830783091b34129a (patch) | |
tree | 9b690a5bcbf2727590bdf5be6eb33ce79ea52d47 | |
parent | 3a3870d7ea1e81e1a145b1d555b9f0164860f9e3 (diff) |
Fix two of my stupid bugs that prevented using the queue with transport streams:
- keep a cache of the pid/substream id mappings from each scan rather than assuming an encode will immediately follow a scan (there will be lots of scans followed by lots of encodes when the queue is used).
- rewrite a few things to get rid of static variables. hb_ts_stream_decode is called by both scan & reader and they're in different threads. All the working storage & state has to either be in the stream struct or on the stack so it's private to the calling thread or it gets corrupted when doing a scan in the middle of an encode.
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1351 b64f7644-9d1e-0410-96f1-a4d463321fa5
-rw-r--r-- | libhb/internal.h | 2 | ||||
-rw-r--r-- | libhb/reader.c | 4 | ||||
-rw-r--r-- | libhb/scan.c | 2 | ||||
-rwxr-xr-x | libhb/stream.c | 562 |
4 files changed, 326 insertions, 244 deletions
diff --git a/libhb/internal.h b/libhb/internal.h index a2b479929..8095967ac 100644 --- a/libhb/internal.h +++ b/libhb/internal.h @@ -136,7 +136,7 @@ int hb_dvd_chapter( hb_dvd_t * ); int hb_dvd_is_break( hb_dvd_t * d ); void hb_dvd_close( hb_dvd_t ** ); -hb_stream_t * hb_stream_open( char * path ); +hb_stream_t * hb_stream_open( char * path, int opentype ); void hb_stream_close( hb_stream_t ** ); hb_title_t * hb_stream_title_scan( hb_stream_t *); int hb_stream_read( hb_stream_t *, hb_buffer_t *); diff --git a/libhb/reader.c b/libhb/reader.c index b2bff03ef..db1c7af72 100644 --- a/libhb/reader.c +++ b/libhb/reader.c @@ -68,7 +68,7 @@ static void ReaderFunc( void * _r ) if( !( r->dvd = hb_dvd_init( r->title->dvd ) ) ) { - if ( !(r->stream = hb_stream_open(r->title->dvd) ) ) + if ( !( r->stream = hb_stream_open( r->title->dvd, 1 ) ) ) { return; } @@ -212,7 +212,7 @@ static void ReaderFunc( void * _r ) * new packet lines up with that of the previous packet. */ int64_t scr_delta = buf->stop - r->last_scr; - if ( scr_delta > 67500 || scr_delta < -900 ) + if ( scr_delta > (90*700) || scr_delta < -90 ) { ++r->scr_changes; r->scr_offset += scr_delta - 1; diff --git a/libhb/scan.c b/libhb/scan.c index e3972a653..5b62fecb0 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -70,7 +70,7 @@ static void ScanFunc( void * _data ) } } } - else if ( (data->stream = hb_stream_open (data->path)) != NULL ) + else if ( (data->stream = hb_stream_open( data->path, 0 ) ) != NULL ) { hb_list_add( data->list_title, hb_stream_title_scan( data->stream ) ); } diff --git a/libhb/stream.c b/libhb/stream.c index 9b6fd432c..e376c6903 100755 --- a/libhb/stream.c +++ b/libhb/stream.c @@ -12,77 +12,92 @@ #define min(a, b) a < b ? a : b -typedef enum { hb_stream_type_unknown = 0, hb_stream_type_transport, hb_stream_type_program } hb_stream_type_t; +typedef enum { + hb_stream_type_unknown = 0, + hb_stream_type_transport, + hb_stream_type_program +} hb_stream_type_t; #define kMaxNumberVideoPIDS 1 -#define kMaxNumberAudioPIDS 16 +#define kMaxNumberAudioPIDS 15 #define kMaxNumberDecodeStreams (kMaxNumberVideoPIDS+kMaxNumberAudioPIDS) #define kMaxNumberPMTStreams 32 struct hb_stream_s { - char * path; - FILE * file_handle; - hb_stream_type_t stream_type; - - int frames; /* video frames so far */ - int errors; /* total errors so far */ - int last_error_frame; /* frame # at last error message */ - int last_error_count; /* # errors at last error message */ - - int64_t ts_lastpcr; /* the last pcr we found in the TS stream */ - int64_t ts_nextpcr; /* the next pcr to put in a PS packet */ - - int ts_video_pids[kMaxNumberVideoPIDS]; - int ts_audio_pids[kMaxNumberAudioPIDS]; - - int ts_number_video_pids; - int ts_number_audio_pids; - - uint8_t *ts_buf[kMaxNumberDecodeStreams]; - int ts_pos[kMaxNumberDecodeStreams]; - int ts_streamid[kMaxNumberDecodeStreams]; - int ts_audio_stream_type[kMaxNumberDecodeStreams]; - int8_t ts_foundfirst[kMaxNumberDecodeStreams]; - int8_t ts_skipbad[kMaxNumberDecodeStreams]; - int8_t ts_streamcont[kMaxNumberDecodeStreams]; - int8_t ts_start[kMaxNumberDecodeStreams]; - - struct { - int lang_code; - int flags; - int rate; - int bitrate; - } a52_info[kMaxNumberAudioPIDS]; - - struct - { - unsigned short program_number; - unsigned short program_map_PID; - } pat_info[kMaxNumberPMTStreams]; - int ts_number_pat_entries; + int frames; /* video frames so far */ + int errors; /* total errors so far */ + int last_error_frame; /* frame # at last error message */ + int last_error_count; /* # errors at last error message */ + + int64_t ts_lastpcr; /* the last pcr we found in the TS stream */ + int64_t ts_nextpcr; /* the next pcr to put in a PS packet */ + + uint8_t *ts_buf[kMaxNumberDecodeStreams]; + int ts_pos[kMaxNumberDecodeStreams]; + int8_t ts_foundfirst[kMaxNumberDecodeStreams]; + int8_t ts_skipbad[kMaxNumberDecodeStreams]; + int8_t ts_streamcont[kMaxNumberDecodeStreams]; + int8_t ts_start[kMaxNumberDecodeStreams]; + + uint8_t *fwrite_buf; /* PS buffer (set by hb_ts_stream_decode) */ + uint8_t *fwrite_buf_orig; /* PS buffer start (set by hb_ts_stream_decode) */ + + /* + * Stuff before this point is dynamic state updated as we read the + * stream. Stuff after this point is stream description state that + * we learn during the initial scan but cache so it can be + * reused during the conversion read. + */ + int16_t ts_video_pids[kMaxNumberVideoPIDS]; + int16_t ts_audio_pids[kMaxNumberAudioPIDS]; + + uint8_t ts_number_video_pids; + uint8_t ts_number_audio_pids; + + uint8_t ts_streamid[kMaxNumberDecodeStreams]; + uint8_t ts_audio_stream_type[kMaxNumberDecodeStreams]; + + char *path; + FILE *file_handle; + hb_stream_type_t stream_type; + int opentype; + + struct { + int lang_code; + int flags; + int rate; + int bitrate; + } a52_info[kMaxNumberAudioPIDS]; + + struct + { + unsigned short program_number; + unsigned short program_map_PID; + } pat_info[kMaxNumberPMTStreams]; + int ts_number_pat_entries; - struct - { - int reading; - unsigned char *tablebuf; - unsigned int tablepos; - unsigned char current_continuity_counter; - - int section_length; - int program_number; - unsigned int PCR_PID; - int program_info_length; - unsigned char *progam_info_descriptor_data; - struct - { - unsigned char stream_type; - unsigned short elementary_PID; - unsigned short ES_info_length; - unsigned char *es_info_descriptor_data; - } pmt_stream_info[kMaxNumberPMTStreams]; - } pmt_info; + struct + { + int reading; + unsigned char *tablebuf; + unsigned int tablepos; + unsigned char current_continuity_counter; + + int section_length; + int program_number; + unsigned int PCR_PID; + int program_info_length; + unsigned char *progam_info_descriptor_data; + struct + { + unsigned char stream_type; + unsigned short elementary_PID; + unsigned short ES_info_length; + unsigned char *es_info_descriptor_data; + } pmt_stream_info[kMaxNumberPMTStreams]; + } pmt_info; }; /*********************************************************************** @@ -101,12 +116,35 @@ static off_t align_to_next_packet(FILE* f); /* * streams have a bunch of state that's learned during the scan. We don't * want to throw away the state when scan does a close then relearn - * everything when reader does an open. So we basically ignore - * a stream close, remember the most recent stream we've opened and only - * delete it when a stream of a different name is opened. + * everything when reader does an open. So we save the stream state on + * the close following a scan and reuse it when 'reader' does an open. */ -static hb_stream_t *current_stream; +static hb_list_t *stream_state_list; +static hb_stream_t *hb_stream_lookup( const char *path ) +{ + if ( stream_state_list == NULL ) + return NULL; + + hb_stream_t *ss; + int i = 0; + + while ( ( ss = hb_list_item( stream_state_list, i++ ) ) != NULL ) + { + if ( strcmp( path, ss->path ) == 0 ) + { + break; + } + } + return ss; +} + +static void hb_stream_state_delete( hb_stream_t *ss ) +{ + hb_list_rem( stream_state_list, ss ); + free( ss->path ); + free( ss ); +} static inline int check_ps_sync(const uint8_t *buf) { @@ -176,10 +214,8 @@ static int hb_stream_get_type(hb_stream_t *stream) return 0; } -static void hb_stream_delete( hb_stream_t ** _d ) +static void hb_stream_delete_dynamic( hb_stream_t *d ) { - hb_stream_t * d = *_d; - if( d->file_handle ) { fclose( d->file_handle ); @@ -196,9 +232,13 @@ static void hb_stream_delete( hb_stream_t ** _d ) d->ts_buf[i] = NULL; } } +} + +static void hb_stream_delete( hb_stream_t *d ) +{ + hb_stream_delete_dynamic( d ); free( d->path ); free( d ); - *_d = NULL; } /*********************************************************************** @@ -206,32 +246,83 @@ static void hb_stream_delete( hb_stream_t ** _d ) *********************************************************************** * **********************************************************************/ -hb_stream_t * hb_stream_open( char * path ) +hb_stream_t * hb_stream_open( char *path, int opentype ) { - if (current_stream) + + FILE *f = fopen( path, "r" ); + if ( f == NULL ) { - if (strcmp( path, current_stream->path ) == 0 ) - { - hb_stream_seek( current_stream, 0. ); - return current_stream; - } - hb_stream_delete( ¤t_stream ); + hb_log( "hb_stream_open: open %s failed", path ); + return NULL; } + hb_stream_t *d = calloc( sizeof( hb_stream_t ), 1 ); + if ( d == NULL ) + { + fclose( f ); + hb_log( "hb_stream_open: can't allocate space for %s stream state", path ); + return NULL; + } - /* open the file and see if it's a type we know about. return a stream - * reference structure if we can deal with it & NULL otherwise. */ - if( ( d->file_handle = fopen( path, "rb" ) ) ) + /* + * if we're opening the stream to read & convert, we need + * the state we saved when we scanned the stream. if we're + * opening the stream to scan it we want to rebuild the state + * (even if we have saved state, the stream may have changed). + */ + hb_stream_t *ss = hb_stream_lookup( path ); + if ( opentype == 1 ) { + /* opening to read - we must have saved state */ + if ( ss == NULL ) + { + hb_log( "hb_stream_open: error: re-opening %s but no scan state", path ); + fclose( f ); + free( d ); + return NULL; + } + /* + * copy the saved state since we might be encoding the same stream + * multiple times. + */ + memcpy( d, ss, sizeof(*d) ); + d->file_handle = f; + d->opentype = opentype; d->path = strdup( path ); - if (d->path != NULL && hb_stream_get_type( d ) != 0 ) + + if ( d->stream_type == hb_stream_type_transport ) { - current_stream = d; - return d; + int i = 0; + for ( ; i < d->ts_number_video_pids + d->ts_number_audio_pids; i++) + { + d->ts_buf[i] = malloc( HB_DVD_READ_BUFFER_SIZE ); + } + hb_stream_seek( d, 0. ); } - fclose( d->file_handle ); - if (d->path) - free( d->path ); + return d; + } + + /* + * opening for scan - delete any saved state then (re)scan the stream. + * If it's something we can deal with (MPEG2 PS or TS) return a stream + * reference structure & null otherwise. + */ + + if ( ss != NULL ) + { + hb_stream_state_delete( ss ); + } + d->file_handle = f; + d->opentype = opentype; + d->path = strdup( path ); + if (d->path != NULL && hb_stream_get_type( d ) != 0 ) + { + return d; + } + fclose( d->file_handle ); + if (d->path) + { + free( d->path ); } hb_log( "hb_stream_open: open %s failed", path ); free( d ); @@ -252,6 +343,24 @@ void hb_stream_close( hb_stream_t ** _d ) stream->errors, (double)stream->errors * 100. / (double)stream->frames ); } + /* + * if the stream was opened for a scan, cache the result, otherwise delete + * the state. + */ + if ( stream->opentype == 0 ) + { + hb_stream_delete_dynamic( stream ); + if ( stream_state_list == NULL ) + { + stream_state_list = hb_list_init(); + } + hb_list_add( stream_state_list, stream ); + } + else + { + hb_stream_delete( stream ); + } + *_d = NULL; } /* when the file was first opened we made entries for all the audio elementary @@ -960,77 +1069,57 @@ static off_t align_to_next_packet(FILE* f) return pos; } -// ------------------------------------------------------------------------------------ -int bitpos = 0; -unsigned int bitval = 0; -unsigned char* bitbuf = NULL; -unsigned int bitmask[] = { +typedef struct { + uint8_t *buf; + uint32_t val; + int pos; +} bitbuf_t; + +static const unsigned int bitmask[] = { 0x0,0x1,0x3,0x7,0xf,0x1f,0x3f,0x7f,0xff, 0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff, 0x1ffff,0x3ffff,0x7ffff,0xfffff,0x1fffff,0x3fffff,0x7fffff,0xffffff, 0x1ffffff,0x3ffffff,0x7ffffff,0xfffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; -static inline void set_buf(unsigned char* buf, int bufsize, int clear) +static inline void set_buf(bitbuf_t *bb, uint8_t* buf, int bufsize, int clear) { - bitpos = 0; - bitbuf = buf; - bitval = (bitbuf[0] << 24) | (bitbuf[1] << 16) | (bitbuf[2] << 8) | bitbuf[3]; + bb->pos = 0; + bb->buf = buf; + bb->val = (bb->buf[0] << 24) | (bb->buf[1] << 16) | + (bb->buf[2] << 8) | bb->buf[3]; if (clear) - memset(bitbuf, 0, bufsize); + memset(bb->buf, 0, bufsize); } -static inline int buf_size() +static inline int buf_size(bitbuf_t *bb) { - return bitpos >> 3; + return bb->pos >> 3; } -static inline void set_bits(unsigned int val, int bits) -{ - val &= bitmask[bits]; - - while (bits > 0) - { - int bitsleft = (8 - (bitpos & 7)); - if (bits >= bitsleft) - { - bitbuf[bitpos >> 3] |= val >> (bits - bitsleft); - bitpos += bitsleft; - bits -= bitsleft; - val &= bitmask[bits]; - } - else - { - bitbuf[bitpos >> 3] |= val << (bitsleft - bits); - bitpos += bits; - bits = 0; - } - } -} - -static inline unsigned int get_bits(int bits) +static inline unsigned int get_bits(bitbuf_t *bb, int bits) { unsigned int val; - int left = 32 - (bitpos & 31); + int left = 32 - (bb->pos & 31); if (bits < left) { - val = (bitval >> (left - bits)) & bitmask[bits]; - bitpos += bits; + val = (bb->val >> (left - bits)) & bitmask[bits]; + bb->pos += bits; } else { - val = (bitval & bitmask[left]) << (bits - left); - bitpos += left; + val = (bb->val & bitmask[left]) << (bits - left); + bb->pos += left; bits -= left; - int pos = bitpos >> 3; - bitval = (bitbuf[pos] << 24) | (bitbuf[pos + 1] << 16) | (bitbuf[pos + 2] << 8) | bitbuf[pos + 3]; + int pos = bb->pos >> 3; + bb->val = (bb->buf[pos] << 24) | (bb->buf[pos + 1] << 16) | (bb->buf[pos + 2] << 8) | bb->buf[pos + 3]; if (bits > 0) { - val |= (bitval >> (32 - bits)) & bitmask[bits]; - bitpos += bits; + val |= (bb->val >> (32 - bits)) & bitmask[bits]; + bb->pos += bits; } } @@ -1064,49 +1153,50 @@ static void decode_element_descriptors(hb_stream_t* stream, int esindx, int decode_program_map(hb_stream_t* stream) { - set_buf(stream->pmt_info.tablebuf, stream->pmt_info.tablepos, 0); + bitbuf_t bb; + set_buf(&bb, stream->pmt_info.tablebuf, stream->pmt_info.tablepos, 0); - get_bits(8); // table_id - get_bits(4); - unsigned int section_length = get_bits(12); + get_bits(&bb, 8); // table_id + get_bits(&bb, 4); + unsigned int section_length = get_bits(&bb, 12); stream->pmt_info.section_length = section_length; - unsigned int program_number = get_bits(16); + unsigned int program_number = get_bits(&bb, 16); stream->pmt_info.program_number = program_number; - get_bits(2); - get_bits(5); // version_number - get_bits(1); - get_bits(8); // section_number - get_bits(8); // last_section_number - get_bits(3); - unsigned int PCR_PID = get_bits(13); + get_bits(&bb, 2); + get_bits(&bb, 5); // version_number + get_bits(&bb, 1); + get_bits(&bb, 8); // section_number + get_bits(&bb, 8); // last_section_number + get_bits(&bb, 3); + unsigned int PCR_PID = get_bits(&bb, 13); stream->pmt_info.PCR_PID = PCR_PID; - get_bits(4); - unsigned int program_info_length = get_bits(12); + get_bits(&bb, 4); + unsigned int program_info_length = get_bits(&bb, 12); stream->pmt_info.program_info_length = program_info_length; int i=0; unsigned char *descriptor_buf = (unsigned char *) malloc(program_info_length); for (i = 0; i < program_info_length; i++) { - descriptor_buf[i] = get_bits(8); + descriptor_buf[i] = get_bits(&bb, 8); } int cur_pos = 9 /* data after the section length field*/ + program_info_length; int done_reading_stream_types = 0; while (!done_reading_stream_types) { - unsigned char stream_type = get_bits(8); - get_bits(3); - unsigned int elementary_PID = get_bits(13); - get_bits(4); - unsigned int ES_info_length = get_bits(12); + unsigned char stream_type = get_bits(&bb, 8); + get_bits(&bb, 3); + unsigned int elementary_PID = get_bits(&bb, 13); + get_bits(&bb, 4); + unsigned int ES_info_length = get_bits(&bb, 12); int i=0; unsigned char *ES_info_buf = (unsigned char *) malloc(ES_info_length); for (i=0; i < ES_info_length; i++) { - ES_info_buf[i] = get_bits(8); + ES_info_buf[i] = get_bits(&bb, 8); } if (stream_type == 0x02) @@ -1261,17 +1351,18 @@ int decode_PAT(unsigned char *buf, hb_stream_t *stream) unsigned int pos = 0; //while (pos < tablepos) { - set_buf(tablebuf + pos, tablepos - pos, 0); - - unsigned char section_id = get_bits(8); - get_bits(4); - unsigned int section_len = get_bits(12); - get_bits(16); // transport_id - get_bits(2); - get_bits(5); // version_num - get_bits(1); // current_next - get_bits(8); // section_num - get_bits(8); // last_section + bitbuf_t bb; + set_buf(&bb, tablebuf + pos, tablepos - pos, 0); + + unsigned char section_id = get_bits(&bb, 8); + get_bits(&bb, 4); + unsigned int section_len = get_bits(&bb, 12); + get_bits(&bb, 16); // transport_id + get_bits(&bb, 2); + get_bits(&bb, 5); // version_num + get_bits(&bb, 1); // current_next + get_bits(&bb, 8); // section_num + get_bits(&bb, 8); // last_section switch (section_id) { @@ -1284,17 +1375,17 @@ int decode_PAT(unsigned char *buf, hb_stream_t *stream) stream->ts_number_pat_entries = 0; while ((curr_pos < section_len) && (stream->ts_number_pat_entries < kMaxNumberPMTStreams)) { - unsigned int pkt_program_num = get_bits(16); + unsigned int pkt_program_num = get_bits(&bb, 16); stream->pat_info[stream->ts_number_pat_entries].program_number = pkt_program_num; - get_bits(3); // Reserved + get_bits(&bb, 3); // Reserved if (pkt_program_num == 0) { - get_bits(13); // pkt_network_id + get_bits(&bb, 13); // pkt_network_id } else { - unsigned int pkt_program_map_PID = get_bits(13); + unsigned int pkt_program_map_PID = get_bits(&bb, 13); stream->pat_info[stream->ts_number_pat_entries].program_map_PID = pkt_program_map_PID; } curr_pos += 4; @@ -1414,55 +1505,53 @@ static void hb_ts_stream_find_pids(hb_stream_t *stream) } -static uint8_t *fwrite_buf; -static uint8_t *fwrite_buf_orig; - -static void set_fwrite_buf( uint8_t *obuf ) +static void fwrite64( hb_stream_t *stream, void *buf, int size ) { - fwrite_buf = obuf; - fwrite_buf_orig = obuf; -} - -static void fwrite64( void* buf, int size ) -{ - if ( (fwrite_buf - fwrite_buf_orig) + size > 2048 ) + if ( (stream->fwrite_buf - stream->fwrite_buf_orig) + size > 2048 ) { hb_log( "steam fwrite64 buffer overflow - writing %d with %d already", - size, fwrite_buf - fwrite_buf_orig ); + size, stream->fwrite_buf - stream->fwrite_buf_orig ); return; } - memcpy( fwrite_buf, buf, size ); - fwrite_buf += size; + memcpy( stream->fwrite_buf, buf, size ); + stream->fwrite_buf += size; } static void write_pack(hb_stream_t* stream, uint64_t time, int stuffing) { - uint8_t buf[64]; - set_buf(buf, 64, 1); // clear buffer - - set_bits(0x000001ba, 32); // pack id 32 - set_bits(1, 2); // 0x01 2 - set_bits(time >> 30, 3); // system_clock_reference_base 3 - set_bits(1, 1); // marker_bit 1 - set_bits(time >> 15, 15); // system_clock_reference_base 15 - set_bits(1, 1); // marker_bit 1 - set_bits(time, 15); // system_clock_reference_base1 15 - set_bits(1, 1); // marker_bit 1 - set_bits(0, 9); // system_clock_reference_extension 9 - set_bits(1, 1); // marker_bit 1 - set_bits(384000, 22); // program_mux_rate 22 - set_bits(1, 1); // marker_bit 1 - set_bits(1, 1); // marker_bit 1 - set_bits(31, 5); // reserved 5 - set_bits(stuffing, 3); // pack_stuffing_length 3 - while ( --stuffing >= 0 ) - { - set_bits(0xff, 8 ); - } - fwrite64(buf, buf_size()); + uint8_t buf[24]; + + buf[0] = 0x00; // pack id + buf[1] = 0x00; + buf[2] = 0x01; + buf[3] = 0xba; + + buf[4] = 0x44 | // SCR + ( ( ( time >> 30 ) & 7 ) << 3 ) | + ( ( time >> 28 ) & 3 ); + buf[5] = time >> 20; + buf[6] = 0x04 | + ( ( ( time >> 15 ) & 0x1f ) << 3 ) | + ( ( time >> 13 ) & 3 ); + buf[7] = time >> 5; + buf[8] = 0x04 | ( time << 3 ); + + buf[9] = 0x01; // SCR extension + + buf[10] = 384000 >> (22 - 8); // program mux rate + buf[11] = (uint8_t)( 384000 >> (22 - 16) ); + buf[12] = (uint8_t)( 384000 << 2 ) | 0x03; + + buf[13] = 0xf8 | stuffing; + + int i; + for (i = 0; i < stuffing; ++i ) + buf[14+i] = 0xff; + + fwrite64(stream, buf, 14 + stuffing ); } -static void pad_buffer(int pad) +static void pad_buffer(hb_stream_t* stream, int pad) { pad -= 6; @@ -1474,39 +1563,27 @@ static void pad_buffer(int pad) buf[4] = pad >> 8; buf[5] = pad; - fwrite64(buf, 6); + fwrite64(stream, buf, 6); buf[0] = 0xff; while ( --pad >= 0 ) { - fwrite64(buf, 1); + fwrite64(stream, buf, 1); } } -static void make_pes_header(int len, uint8_t streamid) +static void make_pes_header(hb_stream_t* stream, int len, uint8_t streamid) { uint8_t buf[9]; - set_buf(buf, 9, 1); // clear the buffer - - set_bits(0x000001, 24); // packet_start_code_prefix 24 - set_bits(streamid, 8); // directory_stream_id 8 - set_bits(len + 3, 16); // PES_packet_length 16 - set_bits(0x2, 2); // '10' 2 - set_bits(0, 2); // PES_scrambling_control 2 - set_bits(1, 1); // PES_priority 1 - set_bits(0, 1); // data_alignment_indicator 1 - set_bits(0, 1); // copyright 1 - set_bits(0, 1); // original_or_copy 1 - set_bits(0, 2); // PTS_DTS_flags 2 - set_bits(0, 1); // ESCR_flag 1 - set_bits(0, 1); // ES_rate_flag 1 - set_bits(0, 1); // DSM_trick_mode_flag 1 - set_bits(0, 1); // additional_copy_info_flag 1 - set_bits(0, 1); // PES_CRC_flag 1 - set_bits(0, 1); // PES_extension_flag 1 - set_bits(0, 8); // PES_header_data_length 8 - - fwrite64(buf, 9); + + memset(buf, 0, sizeof(buf) ); + buf[2] = 1; + buf[3] = streamid; + buf[4] = ( len + 3 ) >> 8; + buf[5] = len + 3; + buf[6] = 0x88; + + fwrite64(stream, buf, 9); } static void generate_output_data(hb_stream_t *stream, int curstream) @@ -1568,7 +1645,7 @@ static void generate_output_data(hb_stream_t *stream, int curstream) // Write out the PES header int hdrsize = 9 + tdat[8]; - fwrite64(tdat, hdrsize); + fwrite64(stream, tdat, hdrsize); // add a four byte DVD ac3 stream header uint8_t ac3_substream_id[4]; @@ -1577,17 +1654,17 @@ static void generate_output_data(hb_stream_t *stream, int curstream) ac3_substream_id[1] = 0x01; // number of sync words ac3_substream_id[2] = 0x00; // first offset (16 bits) ac3_substream_id[3] = 0x02; - fwrite64(ac3_substream_id, 4); + fwrite64(stream, ac3_substream_id, 4); // add the rest of the data - fwrite64(tdat + hdrsize, stream->ts_pos[curstream] - hdrsize); + fwrite64(stream, tdat + hdrsize, stream->ts_pos[curstream] - hdrsize); } else { // not audio - don't need to modify the stream so write what we've got tdat[4] = plen >> 8; tdat[5] = plen; - fwrite64( tdat, stream->ts_pos[curstream] ); + fwrite64( stream, tdat, stream->ts_pos[curstream] ); } } else @@ -1596,12 +1673,12 @@ static void generate_output_data(hb_stream_t *stream, int curstream) // PES header. AC3 audio also needs its substream header. if ( stream->ts_audio_stream_type[curstream] != 0x81) { - make_pes_header(stream->ts_pos[curstream], + make_pes_header(stream, stream->ts_pos[curstream], stream->ts_streamid[curstream]); } else { - make_pes_header(stream->ts_pos[curstream] + 4, + make_pes_header(stream, stream->ts_pos[curstream] + 4, stream->ts_streamid[curstream]); // add a four byte DVD ac3 stream header @@ -1611,16 +1688,16 @@ static void generate_output_data(hb_stream_t *stream, int curstream) ac3_substream_id[1] = 0x01; // number of sync words ac3_substream_id[2] = 0x00; // first offset (16 bits) ac3_substream_id[3] = 0x02; - fwrite64(ac3_substream_id, 4); + fwrite64(stream, ac3_substream_id, 4); } - fwrite64( tdat, stream->ts_pos[curstream] ); + fwrite64( stream, tdat, stream->ts_pos[curstream] ); } // Write padding int left = HB_DVD_READ_BUFFER_SIZE - len; if ( left >= 8 ) { - pad_buffer(left); + pad_buffer(stream, left); } stream->ts_pos[curstream] = 0; @@ -1717,7 +1794,12 @@ static int hb_ts_stream_decode( hb_stream_t *stream, uint8_t *obuf ) int curstream; uint8_t buf[188]; - set_fwrite_buf( obuf ); + /* + * stash the output buffer pointer in our stream so we don't have to + * pass it & its original value to everything we call. + */ + stream->fwrite_buf = obuf; + stream->fwrite_buf_orig = obuf; // spin until we get a packet of data from some stream or hit eof while ( 1 ) |