mpegts: MP4 OD support
This commit is contained in:
parent
4682a1dc3a
commit
c530267024
@ -148,6 +148,7 @@ int ff_mp4_read_descr(AVFormatContext *fc, AVIOContext *pb, int *tag);
|
|||||||
int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext *pb);
|
int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, AVIOContext *pb);
|
||||||
void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id);
|
void ff_mp4_parse_es_descr(AVIOContext *pb, int *es_id);
|
||||||
|
|
||||||
|
#define MP4ODescrTag 0x01
|
||||||
#define MP4IODescrTag 0x02
|
#define MP4IODescrTag 0x02
|
||||||
#define MP4ESDescrTag 0x03
|
#define MP4ESDescrTag 0x03
|
||||||
#define MP4DecConfigDescrTag 0x04
|
#define MP4DecConfigDescrTag 0x04
|
||||||
|
@ -74,6 +74,7 @@ typedef struct MpegTSSectionFilter {
|
|||||||
|
|
||||||
struct MpegTSFilter {
|
struct MpegTSFilter {
|
||||||
int pid;
|
int pid;
|
||||||
|
int es_id;
|
||||||
int last_cc; /* last cc code (-1 if first packet) */
|
int last_cc; /* last cc code (-1 if first packet) */
|
||||||
enum MpegTSFilterType type;
|
enum MpegTSFilterType type;
|
||||||
union {
|
union {
|
||||||
@ -317,6 +318,7 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int
|
|||||||
ts->pids[pid] = filter;
|
ts->pids[pid] = filter;
|
||||||
filter->type = MPEGTS_SECTION;
|
filter->type = MPEGTS_SECTION;
|
||||||
filter->pid = pid;
|
filter->pid = pid;
|
||||||
|
filter->es_id = -1;
|
||||||
filter->last_cc = -1;
|
filter->last_cc = -1;
|
||||||
sec = &filter->u.section_filter;
|
sec = &filter->u.section_filter;
|
||||||
sec->section_cb = section_cb;
|
sec->section_cb = section_cb;
|
||||||
@ -345,6 +347,7 @@ static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid,
|
|||||||
ts->pids[pid] = filter;
|
ts->pids[pid] = filter;
|
||||||
filter->type = MPEGTS_PES;
|
filter->type = MPEGTS_PES;
|
||||||
filter->pid = pid;
|
filter->pid = pid;
|
||||||
|
filter->es_id = -1;
|
||||||
filter->last_cc = -1;
|
filter->last_cc = -1;
|
||||||
pes = &filter->u.pes_filter;
|
pes = &filter->u.pes_filter;
|
||||||
pes->pes_cb = pes_cb;
|
pes->pes_cb = pes_cb;
|
||||||
@ -934,6 +937,20 @@ static int parse_MP4IODescrTag(MP4DescrParseContext *d, int64_t off, int len)
|
|||||||
return parse_mp4_descr_arr(d, off, len);
|
return parse_mp4_descr_arr(d, off, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len)
|
||||||
|
{
|
||||||
|
int id_flags;
|
||||||
|
if (len < 2)
|
||||||
|
return 0;
|
||||||
|
id_flags = avio_rb16(&d->pb);
|
||||||
|
if (!(id_flags & 0x0020)) { //URL_Flag
|
||||||
|
update_offsets(&d->pb, &off, &len);
|
||||||
|
return parse_mp4_descr_arr(d, off, len); //ES_Descriptor[]
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
|
static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
|
||||||
{
|
{
|
||||||
int es_id = 0;
|
int es_id = 0;
|
||||||
@ -987,6 +1004,9 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
|
|||||||
case MP4IODescrTag:
|
case MP4IODescrTag:
|
||||||
parse_MP4IODescrTag(d, off, len1);
|
parse_MP4IODescrTag(d, off, len1);
|
||||||
break;
|
break;
|
||||||
|
case MP4ODescrTag:
|
||||||
|
parse_MP4ODescrTag(d, off, len1);
|
||||||
|
break;
|
||||||
case MP4ESDescrTag:
|
case MP4ESDescrTag:
|
||||||
parse_MP4ESDescrTag(d, off, len1);
|
parse_MP4ESDescrTag(d, off, len1);
|
||||||
break;
|
break;
|
||||||
@ -1014,6 +1034,70 @@ static int mp4_read_iods(AVFormatContext *s, const uint8_t *buf, unsigned size,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size,
|
||||||
|
Mp4Descr *descr, int *descr_count, int max_descr_count)
|
||||||
|
{
|
||||||
|
MP4DescrParseContext d;
|
||||||
|
if (init_MP4DescrParseContext(&d, s, buf, size, descr, max_descr_count) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
parse_mp4_descr_arr(&d, avio_tell(&d.pb), size);
|
||||||
|
|
||||||
|
*descr_count = d.descr_count;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SL_packet(AVFormatContext *s, MpegTSContext *ts, const uint8_t *p, const uint8_t *p_end)
|
||||||
|
{
|
||||||
|
AVIOContext pb;
|
||||||
|
Mp4Descr mp4_descr[MAX_MP4_DESCR_COUNT] = {{ 0 }};
|
||||||
|
int mp4_descr_count = 0;
|
||||||
|
int i, pid;
|
||||||
|
|
||||||
|
mp4_read_od(s, p, (unsigned)(p_end - p), mp4_descr, &mp4_descr_count, MAX_MP4_DESCR_COUNT);
|
||||||
|
|
||||||
|
for (pid = 0; pid < NB_PID_MAX; pid++) {
|
||||||
|
if (!ts->pids[pid])
|
||||||
|
continue;
|
||||||
|
for (i = 0; i < mp4_descr_count; i++) {
|
||||||
|
PESContext *pes;
|
||||||
|
AVStream *st;
|
||||||
|
if (ts->pids[pid]->es_id != mp4_descr[i].es_id)
|
||||||
|
continue;
|
||||||
|
if (!(ts->pids[pid] && ts->pids[pid]->type == MPEGTS_PES)) {
|
||||||
|
av_log(s, AV_LOG_ERROR, "pid %x is not PES\n", pid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pes = ts->pids[pid]->u.pes_filter.opaque;
|
||||||
|
st = pes->st;
|
||||||
|
if (!st) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ffio_init_context(&pb, mp4_descr[i].dec_config_descr,
|
||||||
|
mp4_descr[i].dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
|
||||||
|
ff_mp4_read_dec_config_descr(s, st, &pb);
|
||||||
|
if (st->codec->codec_id == CODEC_ID_AAC &&
|
||||||
|
st->codec->extradata_size > 0)
|
||||||
|
st->need_parsing = 0;
|
||||||
|
if (st->codec->codec_id == CODEC_ID_H264 &&
|
||||||
|
st->codec->extradata_size > 0)
|
||||||
|
st->need_parsing = 0;
|
||||||
|
|
||||||
|
if (st->codec->codec_id <= CODEC_ID_NONE) {
|
||||||
|
} else if (st->codec->codec_id < CODEC_ID_FIRST_AUDIO) {
|
||||||
|
st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
|
||||||
|
} else if (st->codec->codec_id < CODEC_ID_FIRST_SUBTITLE) {
|
||||||
|
st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
|
||||||
|
} else if (st->codec->codec_id < CODEC_ID_FIRST_UNKNOWN) {
|
||||||
|
st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < mp4_descr_count; i++)
|
||||||
|
av_free(mp4_descr[i].dec_config_descr);
|
||||||
|
}
|
||||||
|
|
||||||
static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
|
static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
|
||||||
{
|
{
|
||||||
MpegTSContext *ts = filter->u.section_filter.opaque;
|
MpegTSContext *ts = filter->u.section_filter.opaque;
|
||||||
@ -1030,6 +1114,7 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le
|
|||||||
if (h->tid != M4OD_TID)
|
if (h->tid != M4OD_TID)
|
||||||
return;
|
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,
|
||||||
@ -1061,6 +1146,8 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
|
|||||||
switch(desc_tag) {
|
switch(desc_tag) {
|
||||||
case 0x1E: /* SL descriptor */
|
case 0x1E: /* SL descriptor */
|
||||||
desc_es_id = get16(pp, desc_end);
|
desc_es_id = get16(pp, desc_end);
|
||||||
|
if (ts && ts->pids[pid])
|
||||||
|
ts->pids[pid]->es_id = desc_es_id;
|
||||||
for (i = 0; i < mp4_descr_count; i++)
|
for (i = 0; i < mp4_descr_count; i++)
|
||||||
if (mp4_descr[i].dec_config_descr_len &&
|
if (mp4_descr[i].dec_config_descr_len &&
|
||||||
mp4_descr[i].es_id == desc_es_id) {
|
mp4_descr[i].es_id == desc_es_id) {
|
||||||
@ -1258,6 +1345,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
|||||||
} else {
|
} else {
|
||||||
st = avformat_new_stream(pes->stream, NULL);
|
st = avformat_new_stream(pes->stream, NULL);
|
||||||
st->id = pid;
|
st->id = pid;
|
||||||
|
st->codec->codec_type = AVMEDIA_TYPE_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user