summaryrefslogtreecommitdiff
path: root/libavformat/hevc.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2014-03-09 23:07:48 +0100
committerMichael Niedermayer <michaelni@gmx.at>2014-03-09 23:08:33 +0100
commita379813ceed6b24c149aa8e50a7bd2b09639208a (patch)
tree2282139849530947c3dabb6b430291cf071fc83c /libavformat/hevc.c
parentcb403b2570385cbf48a11f9f48441de5cd01171e (diff)
parentb6c61fb83e876d404ac3b0b3657ebfcafdcd1926 (diff)
Merge commit 'b6c61fb83e876d404ac3b0b3657ebfcafdcd1926'
* commit 'b6c61fb83e876d404ac3b0b3657ebfcafdcd1926': movenc: enable Annex B to MP4 conversion for HEVC tracks. Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat/hevc.c')
-rw-r--r--libavformat/hevc.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/libavformat/hevc.c b/libavformat/hevc.c
index e799b48df7..6e935e6038 100644
--- a/libavformat/hevc.c
+++ b/libavformat/hevc.c
@@ -1014,6 +1014,107 @@ static int hvcc_write(AVIOContext *pb, HEVCDecoderConfigurationRecord *hvcc)
return 0;
}
+int ff_hevc_annexb2mp4(AVIOContext *pb, const uint8_t *buf_in,
+ int size, int filter_ps, int *ps_count)
+{
+ int num_ps = 0, ret = 0;
+ uint8_t *buf, *end, *start = NULL;
+
+ if (!filter_ps) {
+ ret = ff_avc_parse_nal_units(pb, buf_in, size);
+ goto end;
+ }
+
+ ret = ff_avc_parse_nal_units_buf(buf_in, &start, &size);
+ if (ret < 0)
+ goto end;
+
+ ret = 0;
+ buf = start;
+ end = start + size;
+
+ while (end - buf > 4) {
+ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
+ uint8_t type = (buf[4] >> 1) & 0x3f;
+
+ buf += 4;
+
+ switch (type) {
+ case NAL_VPS:
+ case NAL_SPS:
+ case NAL_PPS:
+ num_ps++;
+ break;
+ default:
+ ret += 4 + len;
+ avio_wb32(pb, len);
+ avio_write(pb, buf, len);
+ break;
+ }
+
+ buf += len;
+ }
+
+end:
+ free(start);
+ if (ps_count)
+ *ps_count = num_ps;
+ return ret;
+}
+
+int ff_hevc_annexb2mp4_buf(const uint8_t *buf_in, uint8_t **buf_out,
+ int *size, int filter_ps, int *ps_count)
+{
+ AVIOContext *pb;
+ int num_ps = 0, ret = 0;
+ uint8_t *buf, *end, *start = NULL;
+
+ if (!filter_ps) {
+ ret = ff_avc_parse_nal_units_buf(buf_in, buf_out, size);
+ goto end;
+ }
+
+ ret = avio_open_dyn_buf(&pb);
+ if (ret < 0)
+ goto end;
+
+ ret = ff_avc_parse_nal_units_buf(buf_in, &start, size);
+ if (ret < 0)
+ goto end;
+
+ buf = start;
+ end = start + *size;
+
+ while (end - buf > 4) {
+ uint32_t len = FFMIN(AV_RB32(buf), end - buf - 4);
+ uint8_t type = (buf[4] >> 1) & 0x3f;
+
+ buf += 4;
+
+ switch (type) {
+ case NAL_VPS:
+ case NAL_SPS:
+ case NAL_PPS:
+ num_ps++;
+ break;
+ default:
+ avio_wb32(pb, len);
+ avio_write(pb, buf, len);
+ break;
+ }
+
+ buf += len;
+ }
+
+ *size = avio_close_dyn_buf(pb, buf_out);
+
+end:
+ free(start);
+ if (ps_count)
+ *ps_count = num_ps;
+ return ret;
+}
+
int ff_isom_write_hvcc(AVIOContext *pb, const uint8_t *data,
int size, int ps_array_completeness)
{