Commit ca65932b authored by Alex Converse's avatar Alex Converse

mpegts: MP4 SL support

parent c5302670
...@@ -153,6 +153,7 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id); ...@@ -153,6 +153,7 @@ void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id);
#define MP4ESDescrTag 0x03 #define MP4ESDescrTag 0x03
#define MP4DecConfigDescrTag 0x04 #define MP4DecConfigDescrTag 0x04
#define MP4DecSpecificDescrTag 0x05 #define MP4DecSpecificDescrTag 0x05
#define MP4SLDescrTag 0x06
int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb, MOVAtom atom); int ff_mov_read_esds(AVFormatContext *fc, AVIOContext *pb, MOVAtom atom);
enum CodecID ff_mov_get_lpcm_codec_id(int bps, int flags); enum CodecID ff_mov_get_lpcm_codec_id(int bps, int flags);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#include "libavcodec/bytestream.h" #include "libavcodec/bytestream.h"
#include "libavcodec/get_bits.h"
#include "avformat.h" #include "avformat.h"
#include "mpegts.h" #include "mpegts.h"
#include "internal.h" #include "internal.h"
...@@ -175,6 +176,7 @@ typedef struct PESContext { ...@@ -175,6 +176,7 @@ typedef struct PESContext {
int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */ int64_t ts_packet_pos; /**< position of first TS packet of this PES packet */
uint8_t header[MAX_PES_HEADER_SIZE]; uint8_t header[MAX_PES_HEADER_SIZE];
uint8_t *buffer; uint8_t *buffer;
SLConfigDescr sl;
} PESContext; } PESContext;
extern AVInputFormat ff_mpegts_demuxer; extern AVInputFormat ff_mpegts_demuxer;
...@@ -658,6 +660,83 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt) ...@@ -658,6 +660,83 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
pes->flags = 0; pes->flags = 0;
} }
static uint64_t get_bits64(GetBitContext *gb, int bits)
{
uint64_t ret = 0;
while (bits > 17) {
ret <<= 17;
ret |= get_bits(gb, 17);
bits -= 17;
}
ret <<= bits;
ret |= get_bits(gb, bits);
return ret;
}
static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf, int buf_size)
{
GetBitContext gb;
int au_start_flag = 0, au_end_flag = 0, ocr_flag = 0, idle_flag = 0;
int padding_flag = 0, padding_bits = 0, inst_bitrate_flag = 0;
int dts_flag = -1, cts_flag = -1;
int64_t dts = AV_NOPTS_VALUE, cts = AV_NOPTS_VALUE;
init_get_bits(&gb, buf, buf_size*8);
if (sl->use_au_start)
au_start_flag = get_bits1(&gb);
if (sl->use_au_end)
au_end_flag = get_bits1(&gb);
if (!sl->use_au_start && !sl->use_au_end)
au_start_flag = au_end_flag = 1;
if (sl->ocr_len > 0)
ocr_flag = get_bits1(&gb);
if (sl->use_idle)
idle_flag = get_bits1(&gb);
if (sl->use_padding)
padding_flag = get_bits1(&gb);
if (padding_flag)
padding_bits = get_bits(&gb, 3);
if (!idle_flag && (!padding_flag || padding_bits != 0)) {
if (sl->packet_seq_num_len)
skip_bits_long(&gb, sl->packet_seq_num_len);
if (sl->degr_prior_len)
if (get_bits1(&gb))
skip_bits(&gb, sl->degr_prior_len);
if (ocr_flag)
skip_bits_long(&gb, sl->ocr_len);
if (au_start_flag) {
if (sl->use_rand_acc_pt)
get_bits1(&gb);
if (sl->au_seq_num_len > 0)
skip_bits_long(&gb, sl->au_seq_num_len);
if (sl->use_timestamps) {
dts_flag = get_bits1(&gb);
cts_flag = get_bits1(&gb);
}
}
if (sl->inst_bitrate_len)
inst_bitrate_flag = get_bits1(&gb);
if (dts_flag == 1)
dts = get_bits64(&gb, sl->timestamp_len);
if (cts_flag == 1)
cts = get_bits64(&gb, sl->timestamp_len);
if (sl->au_len > 0)
skip_bits_long(&gb, sl->au_len);
if (inst_bitrate_flag)
skip_bits_long(&gb, sl->inst_bitrate_len);
}
if (dts != AV_NOPTS_VALUE)
pes->dts = dts;
if (cts != AV_NOPTS_VALUE)
pes->pts = cts;
av_set_pts_info(pes->st, sl->timestamp_len, 1, sl->timestamp_res);
return (get_bits_count(&gb) + 7) >> 3;
}
/* return non zero if a packet could be constructed */ /* return non zero if a packet could be constructed */
static int mpegts_push_data(MpegTSFilter *filter, static int mpegts_push_data(MpegTSFilter *filter,
const uint8_t *buf, int buf_size, int is_start, const uint8_t *buf, int buf_size, int is_start,
...@@ -809,6 +888,12 @@ static int mpegts_push_data(MpegTSFilter *filter, ...@@ -809,6 +888,12 @@ static int mpegts_push_data(MpegTSFilter *filter,
/* we got the full header. We parse it and get the payload */ /* we got the full header. We parse it and get the payload */
pes->state = MPEGTS_PAYLOAD; pes->state = MPEGTS_PAYLOAD;
pes->data_index = 0; pes->data_index = 0;
if (pes->stream_type == 0x12) {
int sl_header_bytes = read_sl_header(pes, &pes->sl, p, buf_size);
pes->pes_header_size += sl_header_bytes;
p += sl_header_bytes;
buf_size -= sl_header_bytes;
}
} }
break; break;
case MPEGTS_PAYLOAD: case MPEGTS_PAYLOAD:
...@@ -962,7 +1047,9 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len) ...@@ -962,7 +1047,9 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
d->active_descr->es_id = es_id; d->active_descr->es_id = es_id;
update_offsets(&d->pb, &off, &len); update_offsets(&d->pb, &off, &len);
parse_mp4_descr(d, off, len, MP4DecConfigDescrTag); parse_mp4_descr(d, off, len, MP4DecConfigDescrTag);
//SLConfigDescriptor update_offsets(&d->pb, &off, &len);
if (len > 0)
parse_mp4_descr(d, off, len, MP4SLDescrTag);
d->active_descr = NULL; d->active_descr = NULL;
return 0; return 0;
} }
...@@ -980,6 +1067,39 @@ static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off, int ...@@ -980,6 +1067,39 @@ static int parse_MP4DecConfigDescrTag(MP4DescrParseContext *d, int64_t off, int
return 0; return 0;
} }
static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
{
Mp4Descr *descr = d->active_descr;
int predefined;
if (!descr)
return -1;
predefined = avio_r8(&d->pb);
if (!predefined) {
int lengths;
int flags = avio_r8(&d->pb);
descr->sl.use_au_start = !!(flags & 0x80);
descr->sl.use_au_end = !!(flags & 0x40);
descr->sl.use_rand_acc_pt = !!(flags & 0x20);
descr->sl.use_padding = !!(flags & 0x08);
descr->sl.use_timestamps = !!(flags & 0x04);
descr->sl.use_idle = !!(flags & 0x02);
descr->sl.timestamp_res = avio_rb32(&d->pb);
avio_rb32(&d->pb);
descr->sl.timestamp_len = avio_r8(&d->pb);
descr->sl.ocr_len = avio_r8(&d->pb);
descr->sl.au_len = avio_r8(&d->pb);
descr->sl.inst_bitrate_len = avio_r8(&d->pb);
lengths = avio_rb16(&d->pb);
descr->sl.degr_prior_len = lengths >> 12;
descr->sl.au_seq_num_len = (lengths >> 7) & 0x1f;
descr->sl.packet_seq_num_len = (lengths >> 2) & 0x1f;
} else {
av_log_missing_feature(d->s, "Predefined SLConfigDescriptor\n", 0);
}
return 0;
}
static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
int target_tag) { int target_tag) {
int tag; int tag;
...@@ -1013,6 +1133,9 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len, ...@@ -1013,6 +1133,9 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
case MP4DecConfigDescrTag: case MP4DecConfigDescrTag:
parse_MP4DecConfigDescrTag(d, off, len1); parse_MP4DecConfigDescrTag(d, off, len1);
break; break;
case MP4SLDescrTag:
parse_MP4SLDescrTag(d, off, len1);
break;
} }
done: done:
...@@ -1047,12 +1170,23 @@ static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size, ...@@ -1047,12 +1170,23 @@ static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size,
return 0; return 0;
} }
static void SL_packet(AVFormatContext *s, MpegTSContext *ts, const uint8_t *p, const uint8_t *p_end) static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{ {
MpegTSContext *ts = filter->u.section_filter.opaque;
SectionHeader h;
const uint8_t *p, *p_end;
AVIOContext pb; AVIOContext pb;
Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }}; Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }};
int mp4_descr_count = 0; int mp4_descr_count = 0;
int i, pid; int i, pid;
AVFormatContext *s = ts->stream;
p_end = section + section_len - 4;
p = section;
if (parse_section_header(&h, &p, p_end) < 0)
return;
if (h.tid != M4OD_TID)
return;
mp4_read_od(s, p, (unsigned)(p_end - p), mp4_descr, &mp4_descr_count, MAX_MP4_DESCR_COUNT); mp4_read_od(s, p, (unsigned)(p_end - p), mp4_descr, &mp4_descr_count, MAX_MP4_DESCR_COUNT);
...@@ -1074,6 +1208,8 @@ static void SL_packet(AVFormatContext *s, MpegTSContext *ts, const uint8_t *p, c ...@@ -1074,6 +1208,8 @@ static void SL_packet(AVFormatContext *s, MpegTSContext *ts, const uint8_t *p, c
continue; continue;
} }
pes->sl = mp4_descr[i].sl;
ffio_init_context(&pb, mp4_descr[i].dec_config_descr, ffio_init_context(&pb, mp4_descr[i].dec_config_descr,
mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL); mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
ff_mp4_read_dec_config_descr(s, st, &pb); ff_mp4_read_dec_config_descr(s, st, &pb);
...@@ -1098,25 +1234,6 @@ static void SL_packet(AVFormatContext *s, MpegTSContext *ts, const uint8_t *p, c ...@@ -1098,25 +1234,6 @@ static void SL_packet(AVFormatContext *s, MpegTSContext *ts, const uint8_t *p, c
av_free(mp4_descr[i].dec_config_descr); av_free(mp4_descr[i].dec_config_descr);
} }
static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
{
MpegTSContext *ts = filter->u.section_filter.opaque;
SectionHeader h1, *h = &h1;
const uint8_t *p, *p_end;
av_dlog(ts->stream, "m4SL/od:\n");
hex_dump_debug(ts->stream, (uint8_t *)section, section_len);
p_end = section + section_len - 4;
p = section;
if (parse_section_header(h, &p, p_end) < 0)
return;
if (h->tid != M4OD_TID)
return;
SL_packet(ts->stream, ts, p, p_end);
}
int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type, int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type,
const uint8_t **pp, const uint8_t *desc_list_end, const uint8_t **pp, const uint8_t *desc_list_end,
Mp4Descr *mp4_descr, int mp4_descr_count, int pid, Mp4Descr *mp4_descr, int mp4_descr_count, int pid,
......
...@@ -65,10 +65,28 @@ int ff_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt, ...@@ -65,10 +65,28 @@ int ff_mpegts_parse_packet(MpegTSContext *ts, AVPacket *pkt,
const uint8_t *buf, int len); const uint8_t *buf, int len);
void ff_mpegts_parse_close(MpegTSContext *ts); void ff_mpegts_parse_close(MpegTSContext *ts);
typedef struct {
int use_au_start;
int use_au_end;
int use_rand_acc_pt;
int use_padding;
int use_timestamps;
int use_idle;
int timestamp_res;
int timestamp_len;
int ocr_len;
int au_len;
int inst_bitrate_len;
int degr_prior_len;
int au_seq_num_len;
int packet_seq_num_len;
} SLConfigDescr;
typedef struct { typedef struct {
int es_id; int es_id;
int dec_config_descr_len; int dec_config_descr_len;
uint8_t *dec_config_descr; uint8_t *dec_config_descr;
SLConfigDescr sl;
} Mp4Descr; } Mp4Descr;
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment