aboutsummaryrefslogtreecommitdiffstats
path: root/libavformat
diff options
context:
space:
mode:
authorIan Caulfield <ian.caulfield@gmx.at>2009-10-05 08:38:39 +0000
committerCarl Eugen Hoyos <cehoyos@rainbow.studorg.tuwien.ac.at>2009-10-05 08:38:39 +0000
commit63380b5e54f64abdde4a8b6bce0d60f1fa4a22a1 (patch)
treef50d85d2db840d24c02aac450bb91ff93e4a19a1 /libavformat
parent55c0e1e6d2174d4da506fd2fe620159f171701df (diff)
downloadffmpeg-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')
-rw-r--r--libavformat/mpegts.c56
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;