Allow the combined TrueHD/AC3 tracks on Blu-Ray discs to be demuxed as two separate streams.

Patch by Ian Caulfield, ian D caulfield A gmail

Originally committed as revision 20168 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Ian Caulfield 2009-10-05 08:38:39 +00:00 committed by Carl Eugen Hoyos
parent 55c0e1e6d2
commit 63380b5e54
1 changed files with 53 additions and 3 deletions

View File

@ -148,11 +148,13 @@ struct PESContext {
MpegTSContext *ts;
AVFormatContext *stream;
AVStream *st;
AVStream *sub_st; /**< stream for the embedded AC3 stream in HDMV TrueHD */
enum MpegTSState state;
/* used to get the format */
int data_index;
int total_size;
int pes_header_size;
int extended_stream_id;
int64_t pts, dts;
int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */
uint8_t header[MAX_PES_HEADER_SIZE];
@ -509,6 +511,7 @@ static const StreamType HDMV_types[] = {
{ 0x80, CODEC_TYPE_AUDIO, CODEC_ID_PCM_BLURAY },
{ 0x81, CODEC_TYPE_AUDIO, CODEC_ID_AC3 },
{ 0x82, CODEC_TYPE_AUDIO, CODEC_ID_DTS },
{ 0x83, CODEC_TYPE_AUDIO, CODEC_ID_TRUEHD },
{ 0x90, CODEC_TYPE_SUBTITLE, CODEC_ID_HDMV_PGS_SUBTITLE },
{ 0 },
};
@ -568,8 +571,32 @@ static AVStream *new_pes_av_stream(PESContext *pes, uint32_t prog_reg_desc, uint
mpegts_find_stream_type(st, pes->stream_type, ISO_types);
if (prog_reg_desc == AV_RL32("HDMV") &&
st->codec->codec_id == CODEC_ID_NONE)
st->codec->codec_id == CODEC_ID_NONE) {
mpegts_find_stream_type(st, pes->stream_type, HDMV_types);
if (pes->stream_type == 0x83) {
// HDMV TrueHD streams also contain an AC3 coded version of the
// audio track - add a second stream for this
AVStream *sub_st;
// priv_data cannot be shared between streams
PESContext *sub_pes = av_malloc(sizeof(*sub_pes));
if (!sub_pes)
return NULL;
memcpy(sub_pes, pes, sizeof(*sub_pes));
sub_st = av_new_stream(pes->stream, pes->pid);
if (!sub_st) {
av_free(sub_pes);
return NULL;
}
av_set_pts_info(sub_st, 33, 1, 90000);
sub_st->priv_data = sub_pes;
sub_st->codec->codec_type = CODEC_TYPE_AUDIO;
sub_st->codec->codec_id = CODEC_ID_AC3;
sub_st->need_parsing = AVSTREAM_PARSE_FULL;
sub_pes->sub_st = pes->sub_st = sub_st;
}
}
if (st->codec->codec_id == CODEC_ID_NONE)
mpegts_find_stream_type(st, pes->stream_type, MISC_types);
@ -730,6 +757,11 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
break;
}
p = desc_end;
if (prog_reg_desc == AV_RL32("HDMV") && stream_type == 0x83 && pes->sub_st) {
av_program_add_stream_index(ts->stream, h->id, pes->sub_st->index);
pes->sub_st->codec->codec_tag = st->codec->codec_tag;
}
}
p = desc_list_end;
}
@ -873,7 +905,11 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
pkt->size = pes->data_index;
memset(pkt->data+pkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
pkt->stream_index = pes->st->index;
// Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID
if (pes->sub_st && pes->stream_type == 0x83 && pes->extended_stream_id == 0x76)
pkt->stream_index = pes->sub_st->index;
else
pkt->stream_index = pes->st->index;
pkt->pts = pes->pts;
pkt->dts = pes->dts;
/* store position of first TS packet of this PES packet */
@ -1005,7 +1041,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
buf_size -= len;
if (pes->data_index == pes->pes_header_size) {
const uint8_t *r;
unsigned int flags;
unsigned int flags, pes_ext, skip;
flags = pes->header[7];
r = pes->header + 9;
@ -1020,6 +1056,20 @@ static int mpegts_push_data(MpegTSFilter *filter,
pes->dts = get_pts(r);
r += 5;
}
pes->extended_stream_id = -1;
if (flags & 0x01) { /* PES extension */
pes_ext = *r++;
/* Skip PES private data, program packet sequence counter and P-STD buffer */
skip = (pes_ext >> 4) & 0xb;
skip += skip & 0x9;
r += skip;
if ((pes_ext & 0x41) == 0x01 &&
(r + 2) <= (pes->header + pes->pes_header_size)) {
/* PES extension 2 */
if ((r[0] & 0x7f) > 0 && (r[1] & 0x80) == 0)
pes->extended_stream_id = r[1];
}
}
/* we got the full header. We parse it and get the payload */
pes->state = MPEGTS_PAYLOAD;