static void hb_ps_stream_find_audio_ids(hb_stream_t *stream, hb_title_t *title);
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.
+ */
+static hb_stream_t *current_stream;
+
static inline int check_ps_sync(const uint8_t *buf)
{
- // must have a Pack header
- // (note: the operator '&' instead of '&&' is used deliberately for better
- // performance with a multi-issue pipeline.)
- return (buf[0] == 0x00) & (buf[1] == 0x00) & (buf[2] == 0x01) & (buf[3] == 0xba);
+ // a legal MPEG program stream must start with a Pack header in the
+ // first four bytes.
+ return (buf[0] == 0x00) && (buf[1] == 0x00) &&
+ (buf[2] == 0x01) && (buf[3] == 0xba);
}
static inline int check_ts_sync(const uint8_t *buf)
{
// must have initial sync byte, no scrambling & a legal adaptation ctrl
- return (buf[0] == 0x47) & ((buf[3] >> 6) == 0) & ((buf[3] >> 4) > 0);
+ return (buf[0] == 0x47) && ((buf[3] >> 6) == 0) && ((buf[3] >> 4) > 0);
}
static inline int have_ts_sync(const uint8_t *buf)
{
- return check_ts_sync(&buf[0*188]) & check_ts_sync(&buf[1*188]) &
- check_ts_sync(&buf[2*188]) & check_ts_sync(&buf[3*188]) &
- check_ts_sync(&buf[4*188]) & check_ts_sync(&buf[5*188]) &
- check_ts_sync(&buf[6*188]) & check_ts_sync(&buf[7*188]);
+ return check_ts_sync(&buf[0*188]) && check_ts_sync(&buf[1*188]) &&
+ check_ts_sync(&buf[2*188]) && check_ts_sync(&buf[3*188]) &&
+ check_ts_sync(&buf[4*188]) && check_ts_sync(&buf[5*188]) &&
+ check_ts_sync(&buf[6*188]) && check_ts_sync(&buf[7*188]);
}
static int hb_stream_check_for_ts(const uint8_t *buf)
{
// program streams should have a Pack header every 2048 bytes.
// check that we have 4 of these.
- return check_ps_sync(&buf[0*2048]) & check_ps_sync(&buf[1*2048]) &
- check_ps_sync(&buf[2*2048]) & check_ps_sync(&buf[3*2048]);
+ return check_ps_sync(&buf[0*2048]) && check_ps_sync(&buf[1*2048]) &&
+ check_ps_sync(&buf[2*2048]) && check_ps_sync(&buf[3*2048]);
}
static int hb_stream_get_type(hb_stream_t *stream)
return 0;
}
-/***********************************************************************
- * hb_stream_open
- ***********************************************************************
- *
- **********************************************************************/
-hb_stream_t * hb_stream_open( char * path )
-{
- hb_stream_t * d;
-
- d = calloc( sizeof( hb_stream_t ), 1 );
-
- /* Open device */
- if( ( d->file_handle = fopen( path, "rb" ) ) )
- {
- d->path = strdup( path );
- if ( hb_stream_get_type( d ) != 0 )
- {
- return d;
- }
- fclose( d->file_handle );
- free( d->path );
- }
- else
- {
- hb_log( "hb_stream_open: fopen failed (%s)", path );
- }
- free( d );
- return NULL;
-}
-
-/***********************************************************************
- * hb_stream_close
- ***********************************************************************
- * Closes and frees everything
- **********************************************************************/
-void hb_stream_close( hb_stream_t ** _d )
+static void hb_stream_delete( hb_stream_t ** _d )
{
hb_stream_t * d = *_d;
*_d = NULL;
}
+/***********************************************************************
+ * hb_stream_open
+ ***********************************************************************
+ *
+ **********************************************************************/
+hb_stream_t * hb_stream_open( char * path )
+{
+ if (current_stream)
+ {
+ if (strcmp( path, current_stream->path ) == 0 )
+ {
+ hb_stream_seek( current_stream, 0. );
+ return current_stream;
+ }
+ hb_stream_delete( ¤t_stream );
+ }
+ hb_stream_t *d = calloc( sizeof( hb_stream_t ), 1 );
+
+ /* 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" ) ) )
+ {
+ d->path = strdup( path );
+ if (d->path != NULL && hb_stream_get_type( d ) != 0 )
+ {
+ current_stream = d;
+ return d;
+ }
+ fclose( d->file_handle );
+ if (d->path)
+ free( d->path );
+ }
+ hb_log( "hb_stream_open: open %s failed", path );
+ free( d );
+ return NULL;
+}
+
+/***********************************************************************
+ * hb_stream_close
+ ***********************************************************************
+ * Closes and frees everything
+ **********************************************************************/
+void hb_stream_close( hb_stream_t ** _d )
+{
+}
+
+/* when the file was first opened we made entries for all the audio elementary
+ * streams we found in it. Streams that were later found during the preview scan
+ * now have an audio codec, type, rate, etc., associated with them. At the end
+ * of the scan we delete all the audio entries that weren't found by the scan
+ * or don't have a format we support. This routine deletes audio entry 'indx'
+ * by copying all later entries down one slot. */
static void hb_stream_delete_audio_entry(hb_stream_t *stream, int indx)
{
int i;
{
stream->ts_audio_pids[indx] = stream->ts_audio_pids[i];
stream->ts_audio_stream_type[indx] = stream->ts_audio_stream_type[i];
+ stream->ts_streamid[stream->ts_number_video_pids + indx] =
+ stream->ts_streamid[stream->ts_number_video_pids + i];
++indx;
}
--stream->ts_number_audio_pids;
return 0;
}
+static uint64_t hb_ps_stream_getVideoPTS(hb_stream_t *stream)
+{
+ hb_buffer_t *buf = hb_buffer_init(HB_DVD_READ_BUFFER_SIZE);
+ hb_list_t *list = hb_list_init();
+ // how many blocks we read while searching for a video PES header
+ int blksleft = 1024;
+ uint64_t pts = 0;
+
+ while (--blksleft >= 0 && hb_stream_read(stream, buf) == 1)
+ {
+ hb_buffer_t *es;
+
+ // 'buf' contains an MPEG2 PACK - get a list of all it's elementary streams
+ hb_demux_ps(buf, list);
+
+ while ( ( es = hb_list_item( list, 0 ) ) )
+ {
+ hb_list_rem( list, es );
+ if ( es->id == 0xe0 )
+ {
+ // this PES contains video - if there's a PTS we're done
+ // hb_demux_ps left the PTS in buf_es->start.
+ if ( es->start != ~0 )
+ {
+ pts = es->start;
+ blksleft = 0;
+ break;
+ }
+ }
+ hb_buffer_close( &es );
+ }
+ }
+ hb_list_empty( &list );
+ hb_buffer_close(&buf);
+ return pts;
+}
+
/***********************************************************************
* hb_stream_duration
***********************************************************************
*
**********************************************************************/
-static void hb_stream_duration(hb_stream_t *stream, hb_title_t *inTitle)
+struct pts_pos {
+ uint64_t pos; /* file position of this PTS sample */
+ uint64_t pts; /* PTS from video stream */
+};
+
+static struct pts_pos hb_sample_pts(hb_stream_t *stream, uint64_t fpos)
{
- // VOB Files often have exceedingly unusual PTS values in them - they will progress for a while
- // and then reset without warning !
- if (strstr(stream->path,".vob") != NULL)
- {
- // So we'll use a 'fake duration' that should give enough time !
- int64_t duration = 4 * 3600 * 90000;
- inTitle->duration = duration; //90LL * dvdtime2msec( &d->pgc->playback_time );
- inTitle->hours = inTitle->duration / 90000 / 3600;
- inTitle->minutes = ( ( inTitle->duration / 90000 ) % 3600 ) / 60;
- inTitle->seconds = ( inTitle->duration / 90000 ) % 60;
- return;
- }
+ struct pts_pos pp = { 0, 0 };
- uint64_t first_pts, last_pts;
- const uint8_t *buf;
-
+ if ( stream->stream_type == hb_stream_type_program )
+ {
+ // round address down to nearest dvd sector start
+ fpos &=~ ( HB_DVD_READ_BUFFER_SIZE - 1 );
+ fseeko( stream->file_handle, fpos, SEEK_SET );
+ pp.pts = hb_ps_stream_getVideoPTS( stream );
+ }
+ else
+ {
+ const uint8_t *buf;
+ fseeko( stream->file_handle, fpos, SEEK_SET );
+ align_to_next_packet( stream->file_handle );
+ buf = hb_ts_stream_getPEStype( stream, stream->ts_video_pids[0] );
+ if ( buf == NULL )
+ {
+ hb_log("hb_sample_pts: couldn't find video packet near %llu", fpos);
+ return pp;
+ }
+ if ( ( buf[7] >> 7 ) != 1 )
+ {
+ hb_log("hb_sample_pts: no PTS in video packet near %llu", fpos);
+ return pp;
+ }
+ pp.pts = ( ( (uint64_t)buf[9] >> 1 ) & 7 << 30 ) |
+ ( (uint64_t)buf[10] << 22 ) |
+ ( ( (uint64_t)buf[11] >> 1 ) << 15 ) |
+ ( (uint64_t)buf[12] << 7 ) |
+ ( (uint64_t)buf[13] >> 1 );
+ }
+ pp.pos = ftello(stream->file_handle);
+ hb_log("hb_sample_pts: pts %lld at %llu", pp.pts, pp.pos );
+ return pp;
+}
+
+static void hb_stream_duration(hb_stream_t *stream, hb_title_t *inTitle)
+{
// To calculate the duration we get video presentation time stamps
// at a couple places in the file then use their difference scaled
// by the ratio of the distance between our measurement points &
// the size of the file. The issue is that our video file may have
// chunks from several different program fragments (main feature,
- // commercials, station id, trailers, etc.) all with their on base
+ // commercials, station id, trailers, etc.) all with their own base
// pts value. We need to difference two pts's from the same program
// fragment. Since extraneous material is very likely at the beginning
// and end of the content, for now we take a time stamp from 25%
// into the file & 75% into the file then double their difference
// to get the total duration.
+ struct pts_pos first_pts, last_pts;
+
fseeko(stream->file_handle, 0, SEEK_END);
uint64_t fsize = ftello(stream->file_handle);
- fseeko(stream->file_handle, fsize >> 2, SEEK_SET);
- align_to_next_packet(stream->file_handle);
- buf = hb_ts_stream_getPEStype(stream, stream->ts_video_pids[0]);
- if (buf == NULL)
- {
- hb_log("hb_stream_duration: couldn't find video start packet");
- return;
- }
- if ((buf[7] >> 7) != 1)
- {
- hb_log("hb_stream_duration: no PTS in initial video packet");
- return;
- }
- first_pts = ( ( (uint64_t)buf[9] >> 1 ) & 7 << 30 ) |
- ( (uint64_t)buf[10] << 22 ) |
- ( ( (uint64_t)buf[11] >> 1 ) << 15 ) |
- ( (uint64_t)buf[12] << 7 ) |
- ( (uint64_t)buf[13] >> 1 );
- hb_log("hb_stream_duration: first pts %lld", first_pts);
-
- // now get a pts from a frame near the end of the file.
- fseeko(stream->file_handle, fsize - (fsize >> 2), SEEK_SET);
- align_to_next_packet(stream->file_handle);
- buf = hb_ts_stream_getPEStype(stream, stream->ts_video_pids[0]);
- if (buf == NULL)
- {
- hb_log("hb_stream_duration: couldn't find video end packet");
- return;
- }
- if ((buf[7] >> 7) != 1)
+ first_pts = hb_sample_pts(stream, fsize >> 2);
+ last_pts = hb_sample_pts(stream, fsize - (fsize >> 2) );
+
+ if ( first_pts.pos && last_pts.pos && first_pts.pos != last_pts.pos )
{
- hb_log("hb_stream_duration: no PTS in final video packet");
- inTitle->duration = 0;
- return;
+ uint64_t dur = ( ( last_pts.pts - first_pts.pts ) * fsize ) /
+ ( last_pts.pos - first_pts.pos );
+ inTitle->duration = dur;
+ dur /= 90000;
+ inTitle->hours = dur / 3600;
+ inTitle->minutes = ( dur % 3600 ) / 60;
+ inTitle->seconds = dur % 60;
}
- last_pts = ( ( (uint64_t)buf[9] >> 1 ) & 7 << 30 ) |
- ( (uint64_t)buf[10] << 22 ) |
- ( ( (uint64_t)buf[11] >> 1 ) << 15 ) |
- ( (uint64_t)buf[12] << 7 ) |
- ( (uint64_t)buf[13] >> 1 );
- hb_log("hb_stream_duration: last pts %lld", last_pts);
-
- inTitle->duration = (last_pts - first_pts) * 2 + 90000 * 60;
- inTitle->hours = inTitle->duration / 90000 / 3600;
- inTitle->minutes = ( ( inTitle->duration / 90000 ) % 3600 ) / 60;
- inTitle->seconds = ( inTitle->duration / 90000 ) % 60;
-
rewind(stream->file_handle);
}
// Transport streams are a little more complex - we might be able to just
// read from the transport stream conversion buffer (if there's enough data)
// or we may need to transfer what's left and fill it again.
- if (src_stream->ps_decode_buffer[read_buffer_index].len - src_stream->ps_decode_buffer[read_buffer_index].read_pos > HB_DVD_READ_BUFFER_SIZE)
+ if (src_stream->ps_decode_buffer[read_buffer_index].len
+ - src_stream->ps_decode_buffer[read_buffer_index].read_pos
+ >= HB_DVD_READ_BUFFER_SIZE)
{
- memcpy(b->data, src_stream->ps_decode_buffer[read_buffer_index].data + src_stream->ps_decode_buffer[read_buffer_index].read_pos,HB_DVD_READ_BUFFER_SIZE);
+ memcpy(b->data,
+ src_stream->ps_decode_buffer[read_buffer_index].data +
+ src_stream->ps_decode_buffer[read_buffer_index].read_pos,
+ HB_DVD_READ_BUFFER_SIZE);
src_stream->ps_decode_buffer[read_buffer_index].read_pos += HB_DVD_READ_BUFFER_SIZE;
return 1;
}
int amt_avail_to_transfer = src_stream->ps_decode_buffer[read_buffer_index].len - src_stream->ps_decode_buffer[read_buffer_index].read_pos;
memcpy(b->data, src_stream->ps_decode_buffer[read_buffer_index].data + src_stream->ps_decode_buffer[read_buffer_index].read_pos, amt_avail_to_transfer);
transfer_size -= amt_avail_to_transfer;
- src_stream->ps_decode_buffer[read_buffer_index].read_pos += amt_avail_to_transfer;
-
+
// Give up this buffer - decoding may well need it, and we're done
+ src_stream->ps_decode_buffer[read_buffer_index].read_pos = 0;
src_stream->ps_decode_buffer[read_buffer_index].write_pos = 0;
src_stream->ps_decode_buffer[read_buffer_index].len = 0;
fseeko(src_stream->file_handle,0 ,SEEK_END);
stream_size = ftello(src_stream->file_handle);
new_pos = (off_t) ((double) (stream_size) * pos_ratio);
+ new_pos &=~ (HB_DVD_READ_BUFFER_SIZE - 1);
int r = fseeko(src_stream->file_handle, new_pos, SEEK_SET);
if (r == -1)
stream->ts_audio_stream_type[aud_pid_index],
audio->id);
stream->ts_audio_stream_type[aud_pid_index] = 0x81;
+ stream->ts_streamid[stream->ts_number_video_pids + aud_pid_index] = buf[3];
}
else if ((buf[3] & 0xe0) == 0xc0)
{
- audio->id = buf[3];
+ audio->id = buf[3] | aud_pid_index;
audio->codec = HB_ACODEC_MPGA;
hb_log("transport stream pid 0x%x (type 0x%x) is MPEG audio id 0x%x",
stream->ts_audio_pids[aud_pid_index],
stream->ts_audio_stream_type[aud_pid_index],
audio->id);
stream->ts_audio_stream_type[aud_pid_index] = 0x03;
+ stream->ts_streamid[stream->ts_number_video_pids + aud_pid_index] = buf[3];
}
}
fseeko(stream->file_handle, cur_pos, SEEK_SET);
{
case 0x0:
audio->codec = HB_ACODEC_MPGA;
- hb_log("hb_ps_stream_find_audio_ids: added MPEG audio stream 0x%x", id);
+ hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id);
break;
case 0x2:
- audio->codec = HB_ACODEC_LPCM;
- hb_log("hb_ps_stream_find_audio_ids: added LPCM audio stream 0x%x", id);
- break;
- case 0x4:
- audio->codec = HB_ACODEC_DCA;
- hb_log("hb_ps_stream_find_audio_ids: added DCA audio stream 0x%x", id);
- break;
+ // type 2 is a DVD subtitle stream - just ignore it */
+ free( audio );
+ return;
case 0x8:
audio->codec = HB_ACODEC_AC3;
- hb_log("hb_ps_stream_find_audio_ids: added AC3 audio stream 0x%x", id);
+ hb_log("add_audio_to_title: added AC3 audio stream 0x%x", id);
break;
+ case 0xa:
+ audio->codec = HB_ACODEC_LPCM;
+ hb_log("add_audio_to_title: added LPCM audio stream 0x%x", id);
+ break;
+ default:
+ hb_log("add_audio_to_title: unknown audio stream type 0x%x", id);
+ free( audio );
+ return;
+
}
hb_list_add( title->list_audio, audio );
}
hb_buffer_t *buf = hb_buffer_init(HB_DVD_READ_BUFFER_SIZE);
hb_list_t *list = hb_list_init();
// how many blocks we read while searching for audio streams
- int blksleft = 2048;
+ int blksleft = 4096;
// there can be at most 16 unique streams in an MPEG PS (8 in a DVD)
// so we use a bitmap to keep track of the ones we've already seen.
// Bit 'i' of smap is set if we've already added the audio for
// audio substream id 'i' to the title's audio list.
uint32_t smap = 0;
- hb_stream_seek(stream, 0.0f);
+ // start looking 20% into the file since there's occasionally no
+ // audio at the beginning (particularly for vobs).
+ hb_stream_seek(stream, 0.2f);
while (--blksleft >= 0 && hb_stream_read(stream, buf) == 1)
{
if (stream->stream_type == hb_stream_type_transport)
{
- // Find the audio stream info for this PID
- int i = (audio->id >> 8) & 0xf;
+ // Find the audio stream info for this PID. The stream index is
+ // the subchannel id which is in the bottom four bits for MPEG audio
+ // and the bottom four bits of the upper byte for everything else.
+ int i = ( audio->id >= 0xd0 ? audio->id >> 8 : audio->id ) & 0xf;
if (i >= stream->ts_number_audio_pids)
{
hb_log("hb_stream_update_audio: no PID for audio stream 0x%x",
audio->id);
return;
}
+ if (audio->id < 0xd0)
+ {
+ /* XXX fake mpeg audio sample rate & bps */
+ stream->a52_info[i].flags = A52_STEREO;
+ stream->a52_info[i].rate = 48000 /*Hz*/;
+ stream->a52_info[i].bitrate = 384000 /*Bps*/;
+ }
lang = lang_for_code(stream->a52_info[i].lang_code);
if (!audio->rate)
}
snprintf( audio->lang, sizeof( audio->lang ), "%s (%s)", strlen(lang->native_name) ? lang->native_name : lang->eng_name,
- audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == HB_ACODEC_MPGA ? "MPEG" : "LPCM" ) );
+ audio->codec == HB_ACODEC_AC3 ? "AC3" : ( audio->codec == HB_ACODEC_MPGA ? "MPEG" : ( audio->codec == HB_ACODEC_DCA ? "DTS" : "LPCM" ) ) );
snprintf( audio->lang_simple, sizeof( audio->lang_simple ), "%s", strlen(lang->native_name) ? lang->native_name : lang->eng_name );
snprintf( audio->iso639_2, sizeof( audio->iso639_2 ), "%s", lang->iso639_2);
for (i = stream->ts_number_video_pids; i < stream->ts_number_video_pids + stream->ts_number_audio_pids; i++)
{
stream->ts_packetbuf[i] = (unsigned char *) malloc(1024 * 1024);
- stream->ts_streamid[i] = 0xBD; // Stream 1 is AC-3 Audio
}
}
{
set_buf(stream->pmt_info.tablebuf, stream->pmt_info.tablepos, 0);
- unsigned char table_id = get_bits(8);
- get_bits(4);
- unsigned int section_length = get_bits(12);
- stream->pmt_info.section_length = section_length;
-
- unsigned int program_number = get_bits(16);
- stream->pmt_info.program_number = program_number;
- get_bits(2);
- unsigned char version_number = get_bits(5);
- get_bits(1);
- unsigned char section_number = get_bits(8);
- unsigned char last_section_number = get_bits(8);
- get_bits(3);
- unsigned int PCR_PID = get_bits(13);
- stream->pmt_info.PCR_PID = PCR_PID;
- get_bits(4);
- unsigned int program_info_length = get_bits(12);
- stream->pmt_info.program_info_length = program_info_length;
+ get_bits(8); // table_id
+ get_bits(4);
+ unsigned int section_length = get_bits(12);
+ stream->pmt_info.section_length = section_length;
+
+ unsigned int program_number = get_bits(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);
+ stream->pmt_info.PCR_PID = PCR_PID;
+ get_bits(4);
+ unsigned int program_info_length = get_bits(12);
+ stream->pmt_info.program_info_length = program_info_length;
int i=0;
unsigned char *descriptor_buf = (unsigned char *) malloc(program_info_length);
set_buf(tablebuf + pos, tablepos - pos, 0);
unsigned char section_id = get_bits(8);
- get_bits(4);
+ get_bits(4);
unsigned int section_len = get_bits(12);
- unsigned int transport_id = get_bits(16);
- get_bits(2);
- unsigned int version_num = get_bits(5);
- unsigned int current_next = get_bits(1);
- unsigned int section_num = get_bits(8);
- unsigned int last_section = get_bits(8);
+ 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
switch (section_id)
{
get_bits(3); // Reserved
if (pkt_program_num == 0)
{
- unsigned int pkt_network_PID = get_bits(13);
+ get_bits(13); // pkt_network_id
}
else
{
return 1;
}
- int index_of_selected_pid = -1;
- if ((index_of_selected_pid = index_of_video_pid(pid,stream)) < 0)
- {
- if ((index_of_selected_pid = index_of_audio_pid(pid,stream)) < 0)
- {
- hb_log("generate_output_data - cannot find pid 0x%x (%d) in selected audio or video pids", pid, pid);
- return 0;
- }
- else
- {
- stream->ts_packetbuf[curstream][pos + 3] = stream->ts_streamid[stream->ts_number_video_pids + index_of_selected_pid];
- }
- }
- else
- stream->ts_packetbuf[curstream][pos + 3] = stream->ts_streamid[index_of_selected_pid];
+ stream->ts_packetbuf[curstream][pos + 3] =
+ stream->ts_streamid[curstream];
// Packet length..
// Subtract pack size (14) and pes id and len (6) from lenth
// Add pes header for next packet
pos -= 9;
-// make_pes_header(stream->ts_packetbuf[curstream] + pos, (pid == stream->ts_video_pids[0] ? stream->ts_streamid[kVideoStream] : stream->ts_streamid[kAudioStream]), 0, -1, -1);
make_pes_header(stream->ts_packetbuf[curstream] + pos, stream->ts_streamid[curstream], 0, -1, -1);
}
+ stream->ts_packetpos[curstream] = 0;
+ stream->ts_streamcont[curstream] = -1;
+
// Write padding
if ((written % HB_DVD_READ_BUFFER_SIZE) != 0)
{
}
}
- stream->ts_packetpos[curstream] = 0;
- stream->ts_streamcont[curstream] = -1;
-
return 0;
}
// Check the next packet to make sure IT starts with a 0x0b77
int plen = 0;
-// if (buf[4 + adapt_len] == 0 && buf[4 + adapt_len + 1] == 0 && // Starting with an mpeg header?
-// buf[4 + adapt_len + 2] == 1 && buf[4 + adapt_len + 3] == 0xBD)
- plen = 9 + buf[4 + adapt_len + 8];
+ plen = 9 + buf[4 + adapt_len + 8];
int pstart = 4 + adapt_len + plen;
if (buf[pstart] != 0x0b || buf[pstart + 1] != 0x77)
{
{
stream->ts_skipbad[i] = 1;
}
- // stream->ts_skipbad[kAudioStream] = stream->ts_skipbad[kVideoStream] = 1;
continue;
}
else if (adaption == 0x2)
adapt_len = buf[4] + 1;
if (adapt_len > 184)
{
- hb_log("hb_ts_stream_decode - Invalid adapt len (was > 183)!");
+ hb_log("hb_ts_stream_decode - Invalid adapt len %d", adapt_len);
for (i=0; i < stream->ts_number_video_pids + stream->ts_number_audio_pids; i++)
{
stream->ts_skipbad[i] = 1;
}
-// stream->ts_skipbad[kAudioStream] = stream->ts_skipbad[kVideoStream] = 1;
}
}
// HBO is slick, it doesn't bother to sync AC3 packets with PES elementary stream packets.. so
// we have to swizzle them together! (ARGHH!)
-// if (pid == stream->ts_audio_pids[0] && start)
- if ((index_of_audio_pid(pid, stream) >= 0) && start)
+ if (start && curstream >= stream->ts_number_video_pids &&
+ stream->ts_audio_stream_type[curstream - stream->ts_number_video_pids]
+ != 0x03)
{
// Is there an AC3 packet start 0b77 code in this packet??
int sync_found = 0;
// Couldn't find an AC3 sync start in this packet.. don't make a PES packet!
if (!sync_found)
{
-// int pos = ftell(fin);
-// error("AC3 packet sync not found in start frame");
-// return 1;
- adapt_len += 9 + buf[4 + adapt_len + 8];
+ adapt_len = 184;
start = 0;
}
}
// Check to see if this is an i_frame (group of picture start)
if (pid == stream->ts_video_pids[0])
{
-// printf("Found Video Start for pid 0x%x\n", pid);
// Look for the Group of Pictures packet.. indicates this is an I-Frame packet..
doing_iframe = 0;
unsigned int strid = 0;
// picture_header, let's see if it's an I-frame
if (i<187)
{
-// int pic_start_code = (buf[i+2] >> 3) & 0x07;
-// hb_log("hb_ts_stream_decode - picture_start_code header value = 0x%x (%d)", pic_start_code, pic_start_code);
// check if picture_coding_type == 1
if ((buf[i+2] & (0x7 << 3)) == (1 << 3))
{
{
// Save the substream id block so we can added it to subsequent blocks
int write_ac3 = 0;
-// if (pid == stream->ts_audio_pids[0] /*&& audstreamid == 0xBD*/)
- if (index_of_audio_pid(pid, stream) >= 0)
+ if (curstream >= stream->ts_number_video_pids)
{
// Curstream is a zero based index of streams and includes both video and audio streams, so we must subtract the numver of video streams
// from the indes value used here since ts_audio_stream_type is indexed only by audio streams.
}
// Add the payload for this packet to the current buffer
- if (stream->ts_foundfirst[curstream] && (184 - adapt_len) > 0)
+ if (!stream->ts_skipbad[curstream] && stream->ts_foundfirst[curstream] &&
+ (184 - adapt_len) > 0)
{
+ // XXX this shouldn't happen but we'll be paranoid
+ if (stream->ts_packetpos[curstream] + 184 - adapt_len > 1024*1024)
+ {
+ hb_log("hb_ts_stream_decode: ts_packetbuf overflow, pos = %d ,"
+ "len = %d", stream->ts_packetpos[curstream],
+ 184 - adapt_len );
+ return;
+ }
memcpy(stream->ts_packetbuf[curstream] + stream->ts_packetpos[curstream], buf + 4 + adapt_len, 184 - adapt_len);
stream->ts_packetpos[curstream] += 184 - adapt_len;
}