|
|
|
@@ -65,6 +65,58 @@ static av_cold int mediacodec_decode_close(AVCodecContext *avctx) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int h264_ps_to_nalu(const uint8_t *src, int src_size, uint8_t **out, int *out_size) |
|
|
|
{ |
|
|
|
int i; |
|
|
|
int ret = 0; |
|
|
|
uint8_t *p = NULL; |
|
|
|
static const uint8_t nalu_header[] = { 0x00, 0x00, 0x00, 0x01 }; |
|
|
|
|
|
|
|
if (!out || !out_size) { |
|
|
|
return AVERROR(EINVAL); |
|
|
|
} |
|
|
|
|
|
|
|
p = av_malloc(sizeof(nalu_header) + src_size); |
|
|
|
if (!p) { |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
|
|
|
|
*out = p; |
|
|
|
*out_size = sizeof(nalu_header) + src_size; |
|
|
|
|
|
|
|
memcpy(p, nalu_header, sizeof(nalu_header)); |
|
|
|
memcpy(p + sizeof(nalu_header), src, src_size); |
|
|
|
|
|
|
|
/* Escape 0x00, 0x00, 0x0{0-3} pattern */ |
|
|
|
for (i = 4; i < *out_size; i++) { |
|
|
|
if (i < *out_size - 3 && |
|
|
|
p[i + 0] == 0 && |
|
|
|
p[i + 1] == 0 && |
|
|
|
p[i + 2] <= 3) { |
|
|
|
uint8_t *new; |
|
|
|
|
|
|
|
*out_size += 1; |
|
|
|
new = av_realloc(*out, *out_size); |
|
|
|
if (!new) { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
goto done; |
|
|
|
} |
|
|
|
*out = p = new; |
|
|
|
|
|
|
|
i = i + 3; |
|
|
|
memmove(p + i, p + i - 1, *out_size - i); |
|
|
|
p[i - 1] = 0x03; |
|
|
|
} |
|
|
|
} |
|
|
|
done: |
|
|
|
if (ret < 0) { |
|
|
|
av_freep(out); |
|
|
|
*out_size = 0; |
|
|
|
} |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
static av_cold int mediacodec_decode_init(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
int i; |
|
|
|
@@ -112,24 +164,19 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) |
|
|
|
} |
|
|
|
|
|
|
|
if (pps && sps) { |
|
|
|
static const uint8_t nal_headers[] = { 0x00, 0x00, 0x00, 0x01 }; |
|
|
|
|
|
|
|
uint8_t *data = NULL; |
|
|
|
size_t data_size = sizeof(nal_headers) + FFMAX(sps->data_size, pps->data_size); |
|
|
|
size_t data_size = 0; |
|
|
|
|
|
|
|
data = av_mallocz(data_size); |
|
|
|
if (!data) { |
|
|
|
ret = AVERROR(ENOMEM); |
|
|
|
if ((ret = h264_ps_to_nalu(sps->data, sps->data_size, &data, &data_size)) < 0) { |
|
|
|
goto done; |
|
|
|
} |
|
|
|
ff_AMediaFormat_setBuffer(format, "csd-0", (void*)data, data_size); |
|
|
|
av_freep(&data); |
|
|
|
|
|
|
|
memcpy(data, nal_headers, sizeof(nal_headers)); |
|
|
|
memcpy(data + sizeof(nal_headers), sps->data, sps->data_size); |
|
|
|
ff_AMediaFormat_setBuffer(format, "csd-0", (void*)data, sizeof(nal_headers) + sps->data_size); |
|
|
|
|
|
|
|
memcpy(data + sizeof(nal_headers), pps->data, pps->data_size); |
|
|
|
ff_AMediaFormat_setBuffer(format, "csd-1", (void*)data, sizeof(nal_headers) + pps->data_size); |
|
|
|
|
|
|
|
if ((ret = h264_ps_to_nalu(pps->data, pps->data_size, &data, &data_size)) < 0) { |
|
|
|
goto done; |
|
|
|
} |
|
|
|
ff_AMediaFormat_setBuffer(format, "csd-1", (void*)data, data_size); |
|
|
|
av_freep(&data); |
|
|
|
} else { |
|
|
|
av_log(avctx, AV_LOG_ERROR, "Could not extract PPS/SPS from extradata"); |
|
|
|
|