diff options
author | James Almer <jamrial@gmail.com> | 2017-11-25 04:36:22 +0300 |
---|---|---|
committer | James Almer <jamrial@gmail.com> | 2017-11-30 06:17:41 +0300 |
commit | 8d33e8661694f45a4552d3a3eff736a0f0d17932 (patch) | |
tree | 8cb325b345697350ee67a181dd01f065f90045c5 /libavformat/avc.c | |
parent | d5af8afbe4698273b2ef9b57487489b40f7888b1 (diff) |
avformat/avc: support writting more than one sps/pps in ff_isom_write_avcc
Addresses ticket #6864
Reviewed-by: Michael Niedermayer <michael@niedermayer.cc>
Signed-off-by: James Almer <jamrial@gmail.com>
Diffstat (limited to 'libavformat/avc.c')
-rw-r--r-- | libavformat/avc.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/libavformat/avc.c b/libavformat/avc.c index d989594bb0..ec50033a04 100644 --- a/libavformat/avc.c +++ b/libavformat/avc.c @@ -20,6 +20,7 @@ */ #include "libavutil/intreadwrite.h" +#include "libavcodec/h264.h" #include "avformat.h" #include "avio.h" #include "avc.h" @@ -105,10 +106,11 @@ int ff_avc_parse_nal_units_buf(const uint8_t *buf_in, uint8_t **buf, int *size) int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) { + AVIOContext *sps_pb = NULL, *pps_pb = NULL; uint8_t *buf = NULL, *end, *start = NULL; uint8_t *sps = NULL, *pps = NULL; uint32_t sps_size = 0, pps_size = 0; - int ret; + int ret, nb_sps = 0, nb_pps = 0; if (len <= 6) return AVERROR_INVALIDDATA; @@ -126,6 +128,13 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) start = buf; end = buf + len; + ret = avio_open_dyn_buf(&sps_pb); + if (ret < 0) + goto fail; + ret = avio_open_dyn_buf(&pps_pb); + if (ret < 0) + goto fail; + /* look for sps and pps */ while (end - buf > 4) { uint32_t size; @@ -135,35 +144,51 @@ int ff_isom_write_avcc(AVIOContext *pb, const uint8_t *data, int len) nal_type = buf[0] & 0x1f; if (nal_type == 7) { /* SPS */ - sps = buf; - sps_size = size; + nb_sps++; + if (size > UINT16_MAX || nb_sps >= H264_MAX_SPS_COUNT) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + avio_wb16(sps_pb, size); + avio_write(sps_pb, buf, size); } else if (nal_type == 8) { /* PPS */ - pps = buf; - pps_size = size; + nb_pps++; + if (size > UINT16_MAX || nb_pps >= H264_MAX_PPS_COUNT) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + avio_wb16(pps_pb, size); + avio_write(pps_pb, buf, size); } buf += size; } + sps_size = avio_close_dyn_buf(sps_pb, &sps); + pps_size = avio_close_dyn_buf(pps_pb, &pps); - if (!sps || !pps || sps_size < 4 || sps_size > UINT16_MAX || pps_size > UINT16_MAX) { + if (sps_size < 6 || !pps_size) { ret = AVERROR_INVALIDDATA; goto fail; } avio_w8(pb, 1); /* version */ - avio_w8(pb, sps[1]); /* profile */ - avio_w8(pb, sps[2]); /* profile compat */ - avio_w8(pb, sps[3]); /* level */ + avio_w8(pb, sps[3]); /* profile */ + avio_w8(pb, sps[4]); /* profile compat */ + avio_w8(pb, sps[5]); /* level */ avio_w8(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */ - avio_w8(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */ + avio_w8(pb, 0xe0 | nb_sps); /* 3 bits reserved (111) + 5 bits number of sps */ - avio_wb16(pb, sps_size); avio_write(pb, sps, sps_size); - avio_w8(pb, 1); /* number of pps */ - avio_wb16(pb, pps_size); + avio_w8(pb, nb_pps); /* number of pps */ avio_write(pb, pps, pps_size); fail: + if (!sps) + avio_close_dyn_buf(sps_pb, &sps); + if (!pps) + avio_close_dyn_buf(pps_pb, &pps); + av_free(sps); + av_free(pps); av_free(start); return ret; |