|
|
|
@ -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; |
|
|
|
|