diff options
author | Ian Caulfield <ian.caulfield@gmx.at> | 2009-10-05 08:38:39 +0000 |
---|---|---|
committer | Carl Eugen Hoyos <cehoyos@rainbow.studorg.tuwien.ac.at> | 2009-10-05 08:38:39 +0000 |
commit | 63380b5e54f64abdde4a8b6bce0d60f1fa4a22a1 (patch) | |
tree | f50d85d2db840d24c02aac450bb91ff93e4a19a1 /libavformat/mpegts.c | |
parent | 55c0e1e6d2174d4da506fd2fe620159f171701df (diff) | |
download | ffmpeg-63380b5e54f64abdde4a8b6bce0d60f1fa4a22a1.tar.gz |
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
Diffstat (limited to 'libavformat/mpegts.c')
-rw-r--r-- | libavformat/mpegts.c | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index 92a29a3b15..76efe30e76 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -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; |