uint8_t ts_number_audio_pids;
uint8_t ts_streamid[kMaxNumberDecodeStreams];
+ uint8_t ts_video_stream_type[kMaxNumberDecodeStreams];
uint8_t ts_audio_stream_type[kMaxNumberDecodeStreams];
char *path;
if ( stream->frames )
{
hb_log( "stream: %d good frames, %d errors (%.0f%%)", stream->frames,
- stream->errors, (double)stream->errors * 100. /
+ stream->errors, (double)stream->errors * 100. /
(double)stream->frames );
}
/*
for (i=0; i < stream->ts_number_audio_pids; i++)
{
hb_audio_t *audio = hb_ts_stream_set_audio_id_and_codec(stream, i);
- if (audio->codec)
+ if (audio->config.in.codec)
hb_list_add( aTitle->list_audio, audio );
else
{
return 1;
}
+static void set_audio_description( hb_audio_t *audio, iso639_lang_t *lang )
+{
+ /* XXX
+ * This is a duplicate of code in dvd.c - it should get factored out
+ * into a common routine. We probably should only be putting the lang
+ * code or a lang pointer into the audio config & let the common description
+ * formatting routine in scan.c do all the stuff below.
+ */
+ snprintf( audio->config.lang.description,
+ sizeof( audio->config.lang.description ), "%s (%s)",
+ strlen(lang->native_name) ? lang->native_name : lang->eng_name,
+ audio->config.in.codec == HB_ACODEC_AC3 ? "AC3" :
+ audio->config.in.codec == HB_ACODEC_DCA ? "DTS" :
+ audio->config.in.codec == HB_ACODEC_MPGA ? "MPEG" : "LPCM" );
+ snprintf( audio->config.lang.simple, sizeof( audio->config.lang.simple ), "%s",
+ strlen(lang->native_name) ? lang->native_name : lang->eng_name );
+ snprintf( audio->config.lang.iso639_2, sizeof( audio->config.lang.iso639_2 ),
+ "%s", lang->iso639_2);
+}
+
static hb_audio_t *hb_ts_stream_set_audio_id_and_codec(hb_stream_t *stream,
int aud_pid_index)
{
if (buf[3] == 0xbd)
{
audio->id = 0x80bd | (aud_pid_index << 8);
- audio->codec = HB_ACODEC_AC3;
+ audio->config.in.codec = HB_ACODEC_AC3;
hb_log("transport stream pid 0x%x (type 0x%x) is AC-3 audio id 0x%x",
stream->ts_audio_pids[aud_pid_index],
stream->ts_audio_stream_type[1 + aud_pid_index],
else if ((buf[3] & 0xe0) == 0xc0)
{
audio->id = buf[3] | aud_pid_index;
- audio->codec = HB_ACODEC_MPGA;
+ audio->config.in.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[1 + aud_pid_index],
}
}
fseeko(stream->file_handle, cur_pos, SEEK_SET);
- if (! audio->codec)
+ if ( audio->config.in.codec )
+ {
+ set_audio_description( audio,
+ lang_for_code( stream->a52_info[aud_pid_index].lang_code ) );
+ }
+ else
{
hb_log("transport stream pid 0x%x (type 0x%x) isn't audio",
stream->ts_audio_pids[aud_pid_index],
switch ( id >> 12 )
{
case 0x0:
- audio->codec = HB_ACODEC_MPGA;
+ audio->config.in.codec = HB_ACODEC_MPGA;
hb_log("add_audio_to_title: added MPEG audio stream 0x%x", id);
break;
case 0x2:
free( audio );
return;
case 0x8:
- audio->codec = HB_ACODEC_AC3;
+ audio->config.in.codec = HB_ACODEC_AC3;
hb_log("add_audio_to_title: added AC3 audio stream 0x%x", id);
break;
case 0xa:
- audio->codec = HB_ACODEC_LPCM;
+ audio->config.in.codec = HB_ACODEC_LPCM;
hb_log("add_audio_to_title: added LPCM audio stream 0x%x", id);
break;
default:
return;
}
+ set_audio_description( audio, lang_for_code( 0 ) );
hb_list_add( title->list_audio, audio );
}
}
/***********************************************************************
- * hb_stream_update_audio
- ***********************************************************************
- *
- **********************************************************************/
-void hb_stream_update_audio(hb_stream_t *stream, hb_audio_t *audio)
-{
- iso639_lang_t *lang;
-
- if (stream->stream_type == hb_stream_type_transport)
- {
- // 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)
- audio->rate = stream->a52_info[i].rate;
- if (!audio->bitrate)
- audio->bitrate = stream->a52_info[i].bitrate;
- if (!audio->config.a52.ac3flags)
- audio->config.a52.ac3flags = audio->ac3flags = stream->a52_info[i].flags;
-
- }
- else
- {
- // XXX should try to get language code from the AC3 bitstream
- lang = lang_for_code(0x0000);
- }
-
- if (!audio->input_channel_layout)
- {
- switch( audio->ac3flags & A52_CHANNEL_MASK )
- {
- /* mono sources */
- case A52_MONO:
- case A52_CHANNEL1:
- case A52_CHANNEL2:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_MONO;
- break;
- /* stereo input */
- case A52_CHANNEL:
- case A52_STEREO:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
- break;
- /* dolby (DPL1 aka Dolby Surround = 4.0 matrix-encoded) input */
- case A52_DOLBY:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_DOLBY;
- break;
- /* 3F/2R input */
- case A52_3F2R:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F2R;
- break;
- /* 3F/1R input */
- case A52_3F1R:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F1R;
- break;
- /* other inputs */
- case A52_3F:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_3F;
- break;
- case A52_2F1R:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F1R;
- break;
- case A52_2F2R:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_2F2R;
- break;
- /* unknown */
- default:
- audio->input_channel_layout = HB_INPUT_CH_LAYOUT_STEREO;
- }
-
- /* add in our own LFE flag if the source has LFE */
- if (audio->ac3flags & A52_LFE)
- {
- audio->input_channel_layout = audio->input_channel_layout | HB_INPUT_CH_LAYOUT_HAS_LFE;
- }
- }
-
- 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" : ( 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);
-
- if ( (audio->ac3flags & A52_CHANNEL_MASK) == A52_DOLBY ) {
- sprintf( audio->lang + strlen( audio->lang ),
- " (Dolby Surround)" );
- } else {
- sprintf( audio->lang + strlen( audio->lang ),
- " (%d.%d ch)",
- HB_INPUT_CH_LAYOUT_GET_DISCRETE_FRONT_COUNT(audio->input_channel_layout) +
- HB_INPUT_CH_LAYOUT_GET_DISCRETE_REAR_COUNT(audio->input_channel_layout),
- HB_INPUT_CH_LAYOUT_GET_DISCRETE_LFE_COUNT(audio->input_channel_layout));
- }
-
- hb_log( "stream: audio %x: lang %s, rate %d, bitrate %d, "
- "flags = 0x%x", audio->id, audio->lang, audio->rate,
- audio->bitrate, audio->ac3flags );
-
-}
-
-/***********************************************************************
* hb_ts_stream_init
***********************************************************************
*
}
}
+/*
+ * Get the name of the stream from the type - thanks to VLC for this.
+ */
+static const char *get_stream_name (unsigned char stream_type)
+{
+ switch( stream_type )
+ {
+ case 0x01: /* MPEG-1 video */
+ case 0x02: /* MPEG-2 video */
+ case 0x80: /* MPEG-2 MOTO video */
+ return("MPEG 1/2 Video");
+ break;
+ case 0x03: /* MPEG-1 audio */
+ case 0x04: /* MPEG-2 audio */
+ return("MPEG Audio");
+ break;
+ case 0x11: /* MPEG4 (audio) */
+ case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS transport syntax */
+ return("MPEG-4 Audio");
+ break;
+ case 0x10: /* MPEG4 (video) */
+ return("MPEG-4 Video");
+ break;
+ case 0x1B: /* H264 <- check transport syntax/needed descriptor */
+ return("H.264 Video");
+ break;
+
+ case 0x81: /* A52 (audio) */
+ return("A52/AC-3 Audio");
+ break;
+ case 0x82: /* DVD_SPU (sub) */
+ return("Subtitle");
+ break;
+ case 0x83: /* LPCM (audio) */
+ return("LPCM Audio");
+ break;
+ case 0x84: /* SDDS (audio) */
+ return("SDDS Audio");
+ break;
+ case 0x85: /* DTS (audio) */
+ return("DTS Audio");
+ break;
+
+ case 0x91: /* A52 vls (audio) */
+ return("A52b/AC-3 Audio");
+ break;
+ case 0x92: /* DVD_SPU vls (sub) */
+ return("Subtitle");
+ break;
+
+ case 0x94: /* SDDS (audio) */
+ return("SDDS Audio");
+ break;
+
+ case 0xa0: /* MSCODEC vlc (video) (fixed later) */
+ return("MSCODEC Video");
+ break;
+
+ case 0x06: /* PES_PRIVATE (fixed later) */
+ case 0x12: /* MPEG-4 generic (sub/scene/...) (fixed later) */
+ case 0xEA: /* Privately managed ES (VC-1) (fixed later */
+ default:
+ return("Other");
+ break;
+ }
+}
+
int decode_program_map(hb_stream_t* stream)
{
bitbuf_t bb;
ES_info_buf[i] = get_bits(&bb, 8);
}
- if (stream_type == 0x02)
+
+ if (stream_type == 0x02 || stream_type == 0x10 || stream_type == 0x1B)
{
- if (stream->ts_number_video_pids <= kMaxNumberVideoPIDS)
+ /* MPEG-2/MPEG-4/H.264 */
+ if (stream->ts_number_video_pids <= kMaxNumberVideoPIDS)
stream->ts_number_video_pids++;
- stream->ts_video_pids[stream->ts_number_video_pids-1] = elementary_PID;
+ stream->ts_video_pids[stream->ts_number_video_pids-1] = elementary_PID;
+ stream->ts_video_stream_type[stream->ts_number_video_pids-1] = stream_type;
}
- else
- {
- // Defined audio stream types are 0x81 for AC-3/A52 audio and 0x03
- // for mpeg audio. But content producers seem to use other
- // values (0x04 and 0x06 have both been observed) so at this point
- // we say everything that isn't a video pid is audio then at the end
- // of hb_stream_title_scan we'll figure out which are really audio
- // by looking at the PES headers.
- i = stream->ts_number_audio_pids;
- if (i < kMaxNumberAudioPIDS)
- stream->ts_number_audio_pids++;
- stream->ts_audio_pids[i] = elementary_PID;
- stream->ts_audio_stream_type[1 + i] = stream_type;
-
- if (ES_info_length > 0)
- {
- decode_element_descriptors(stream, i, ES_info_buf, ES_info_length);
- }
+ else
+ {
+ // Defined audio stream types are 0x81 for AC-3/A52 audio and 0x03
+ // for mpeg audio. But content producers seem to use other
+ // values (0x04 and 0x06 have both been observed) so at this point
+ // we say everything that isn't a video pid is audio then at the end
+ // of hb_stream_title_scan we'll figure out which are really audio
+ // by looking at the PES headers.
+ i = stream->ts_number_audio_pids;
+ if (i < kMaxNumberAudioPIDS)
+ stream->ts_number_audio_pids++;
+ stream->ts_audio_pids[i] = elementary_PID;
+ stream->ts_audio_stream_type[1 + i] = stream_type;
+
+ if (ES_info_length > 0)
+ {
+ decode_element_descriptors(stream, i, ES_info_buf, ES_info_length);
+ }
}
-
+
cur_pos += 5 /* stream header */ + ES_info_length;
free(ES_info_buf);
int i=0;
for (i=0; i < stream->ts_number_video_pids; i++)
{
- hb_log(" 0x%x (%d)", stream->ts_video_pids[i], stream->ts_video_pids[i]);
+ hb_log(" 0x%x (%d) [Type %s (0x%x)]",
+ stream->ts_video_pids[i], stream->ts_video_pids[i],
+ get_stream_name(stream->ts_video_stream_type[i]),
+ stream->ts_video_stream_type[i]);
}
hb_log(" Audio PIDS : ");
for (i = 0; i < stream->ts_number_audio_pids; i++)
{
- hb_log(" 0x%x (%d)", stream->ts_audio_pids[i], stream->ts_audio_pids[i]);
+ hb_log(" 0x%x (%d) [Type %s (0x%x)]",
+ stream->ts_audio_pids[i], stream->ts_audio_pids[i],
+ get_stream_name(stream->ts_audio_stream_type[i]),
+ stream->ts_audio_stream_type[i] );
}
}
// remember the pcr across calls to this routine
stream->ts_lastpcr = pcr;
}
-
+
if ( pcr == -1 )
{
// don't accumulate data until we get a pcr
// so ignore the rest.
continue;
}
- if ( !start && (stream->ts_streamcont[curstream] != -1) &&
+ if ( !start && (stream->ts_streamcont[curstream] != -1) &&
(continuity != ( (stream->ts_streamcont[curstream] + 1) & 0xf ) ) )
{
ts_err( stream, curstream, "continuity error: got %d expected %d",
stream->ts_skipbad[curstream] = 0;
}
- // If we don't have video yet, check to see if this is an
+ // If we don't have video yet, check to see if this is an
// i_frame (group of picture start)
if ( curstream == 0 )
{