1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * HEVC MP4 to Annex B byte stream format filter
3cabdff1aSopenharmony_ci * copyright (c) 2015 Anton Khirnov
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include <string.h>
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
25cabdff1aSopenharmony_ci#include "libavutil/mem.h"
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "bsf.h"
28cabdff1aSopenharmony_ci#include "bsf_internal.h"
29cabdff1aSopenharmony_ci#include "bytestream.h"
30cabdff1aSopenharmony_ci#include "defs.h"
31cabdff1aSopenharmony_ci#include "hevc.h"
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci#define MIN_HEVCC_LENGTH 23
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_citypedef struct HEVCBSFContext {
36cabdff1aSopenharmony_ci    uint8_t  length_size;
37cabdff1aSopenharmony_ci    int      extradata_parsed;
38cabdff1aSopenharmony_ci} HEVCBSFContext;
39cabdff1aSopenharmony_ci
40cabdff1aSopenharmony_cistatic int hevc_extradata_to_annexb(AVBSFContext *ctx)
41cabdff1aSopenharmony_ci{
42cabdff1aSopenharmony_ci    GetByteContext gb;
43cabdff1aSopenharmony_ci    int length_size, num_arrays, i, j;
44cabdff1aSopenharmony_ci    int ret = 0;
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_ci    uint8_t *new_extradata = NULL;
47cabdff1aSopenharmony_ci    size_t   new_extradata_size = 0;
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_ci    bytestream2_init(&gb, ctx->par_in->extradata, ctx->par_in->extradata_size);
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_ci    bytestream2_skip(&gb, 21);
52cabdff1aSopenharmony_ci    length_size = (bytestream2_get_byte(&gb) & 3) + 1;
53cabdff1aSopenharmony_ci    num_arrays  = bytestream2_get_byte(&gb);
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ci    for (i = 0; i < num_arrays; i++) {
56cabdff1aSopenharmony_ci        int type = bytestream2_get_byte(&gb) & 0x3f;
57cabdff1aSopenharmony_ci        int cnt  = bytestream2_get_be16(&gb);
58cabdff1aSopenharmony_ci
59cabdff1aSopenharmony_ci        if (!(type == HEVC_NAL_VPS || type == HEVC_NAL_SPS || type == HEVC_NAL_PPS ||
60cabdff1aSopenharmony_ci              type == HEVC_NAL_SEI_PREFIX || type == HEVC_NAL_SEI_SUFFIX)) {
61cabdff1aSopenharmony_ci            av_log(ctx, AV_LOG_ERROR, "Invalid NAL unit type in extradata: %d\n",
62cabdff1aSopenharmony_ci                   type);
63cabdff1aSopenharmony_ci            ret = AVERROR_INVALIDDATA;
64cabdff1aSopenharmony_ci            goto fail;
65cabdff1aSopenharmony_ci        }
66cabdff1aSopenharmony_ci
67cabdff1aSopenharmony_ci        for (j = 0; j < cnt; j++) {
68cabdff1aSopenharmony_ci            int nalu_len = bytestream2_get_be16(&gb);
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_ci            if (4 + AV_INPUT_BUFFER_PADDING_SIZE + nalu_len > SIZE_MAX - new_extradata_size) {
71cabdff1aSopenharmony_ci                ret = AVERROR_INVALIDDATA;
72cabdff1aSopenharmony_ci                goto fail;
73cabdff1aSopenharmony_ci            }
74cabdff1aSopenharmony_ci            ret = av_reallocp(&new_extradata, new_extradata_size + nalu_len + 4 + AV_INPUT_BUFFER_PADDING_SIZE);
75cabdff1aSopenharmony_ci            if (ret < 0)
76cabdff1aSopenharmony_ci                goto fail;
77cabdff1aSopenharmony_ci
78cabdff1aSopenharmony_ci            AV_WB32(new_extradata + new_extradata_size, 1); // add the startcode
79cabdff1aSopenharmony_ci            bytestream2_get_buffer(&gb, new_extradata + new_extradata_size + 4, nalu_len);
80cabdff1aSopenharmony_ci            new_extradata_size += 4 + nalu_len;
81cabdff1aSopenharmony_ci            memset(new_extradata + new_extradata_size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
82cabdff1aSopenharmony_ci        }
83cabdff1aSopenharmony_ci    }
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_ci    av_freep(&ctx->par_out->extradata);
86cabdff1aSopenharmony_ci    ctx->par_out->extradata      = new_extradata;
87cabdff1aSopenharmony_ci    ctx->par_out->extradata_size = new_extradata_size;
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_ci    if (!new_extradata_size)
90cabdff1aSopenharmony_ci        av_log(ctx, AV_LOG_WARNING, "No parameter sets in the extradata\n");
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci    return length_size;
93cabdff1aSopenharmony_cifail:
94cabdff1aSopenharmony_ci    av_freep(&new_extradata);
95cabdff1aSopenharmony_ci    return ret;
96cabdff1aSopenharmony_ci}
97cabdff1aSopenharmony_ci
98cabdff1aSopenharmony_cistatic int hevc_mp4toannexb_init(AVBSFContext *ctx)
99cabdff1aSopenharmony_ci{
100cabdff1aSopenharmony_ci    HEVCBSFContext *s = ctx->priv_data;
101cabdff1aSopenharmony_ci    int ret;
102cabdff1aSopenharmony_ci
103cabdff1aSopenharmony_ci    if (ctx->par_in->extradata_size < MIN_HEVCC_LENGTH ||
104cabdff1aSopenharmony_ci        AV_RB24(ctx->par_in->extradata) == 1           ||
105cabdff1aSopenharmony_ci        AV_RB32(ctx->par_in->extradata) == 1) {
106cabdff1aSopenharmony_ci        av_log(ctx, AV_LOG_VERBOSE,
107cabdff1aSopenharmony_ci               "The input looks like it is Annex B already\n");
108cabdff1aSopenharmony_ci    } else {
109cabdff1aSopenharmony_ci        ret = hevc_extradata_to_annexb(ctx);
110cabdff1aSopenharmony_ci        if (ret < 0)
111cabdff1aSopenharmony_ci            return ret;
112cabdff1aSopenharmony_ci        s->length_size      = ret;
113cabdff1aSopenharmony_ci        s->extradata_parsed = 1;
114cabdff1aSopenharmony_ci    }
115cabdff1aSopenharmony_ci
116cabdff1aSopenharmony_ci    return 0;
117cabdff1aSopenharmony_ci}
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_cistatic int hevc_mp4toannexb_filter(AVBSFContext *ctx, AVPacket *out)
120cabdff1aSopenharmony_ci{
121cabdff1aSopenharmony_ci    HEVCBSFContext *s = ctx->priv_data;
122cabdff1aSopenharmony_ci    AVPacket *in;
123cabdff1aSopenharmony_ci    GetByteContext gb;
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci    int got_irap = 0;
126cabdff1aSopenharmony_ci    int i, ret = 0;
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci    ret = ff_bsf_get_packet(ctx, &in);
129cabdff1aSopenharmony_ci    if (ret < 0)
130cabdff1aSopenharmony_ci        return ret;
131cabdff1aSopenharmony_ci
132cabdff1aSopenharmony_ci    if (!s->extradata_parsed) {
133cabdff1aSopenharmony_ci        av_packet_move_ref(out, in);
134cabdff1aSopenharmony_ci        av_packet_free(&in);
135cabdff1aSopenharmony_ci        return 0;
136cabdff1aSopenharmony_ci    }
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_ci    bytestream2_init(&gb, in->data, in->size);
139cabdff1aSopenharmony_ci
140cabdff1aSopenharmony_ci    while (bytestream2_get_bytes_left(&gb)) {
141cabdff1aSopenharmony_ci        uint32_t nalu_size = 0;
142cabdff1aSopenharmony_ci        int      nalu_type;
143cabdff1aSopenharmony_ci        int is_irap, add_extradata, extra_size, prev_size;
144cabdff1aSopenharmony_ci
145cabdff1aSopenharmony_ci        if (bytestream2_get_bytes_left(&gb) < s->length_size) {
146cabdff1aSopenharmony_ci            ret = AVERROR_INVALIDDATA;
147cabdff1aSopenharmony_ci            goto fail;
148cabdff1aSopenharmony_ci        }
149cabdff1aSopenharmony_ci        for (i = 0; i < s->length_size; i++)
150cabdff1aSopenharmony_ci            nalu_size = (nalu_size << 8) | bytestream2_get_byte(&gb);
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_ci        if (nalu_size < 2 || nalu_size > bytestream2_get_bytes_left(&gb)) {
153cabdff1aSopenharmony_ci            ret = AVERROR_INVALIDDATA;
154cabdff1aSopenharmony_ci            goto fail;
155cabdff1aSopenharmony_ci        }
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_ci        nalu_type = (bytestream2_peek_byte(&gb) >> 1) & 0x3f;
158cabdff1aSopenharmony_ci
159cabdff1aSopenharmony_ci        /* prepend extradata to IRAP frames */
160cabdff1aSopenharmony_ci        is_irap       = nalu_type >= 16 && nalu_type <= 23;
161cabdff1aSopenharmony_ci        add_extradata = is_irap && !got_irap;
162cabdff1aSopenharmony_ci        extra_size    = add_extradata * ctx->par_out->extradata_size;
163cabdff1aSopenharmony_ci        got_irap     |= is_irap;
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ci        if (FFMIN(INT_MAX, SIZE_MAX) < 4ULL + nalu_size + extra_size) {
166cabdff1aSopenharmony_ci            ret = AVERROR_INVALIDDATA;
167cabdff1aSopenharmony_ci            goto fail;
168cabdff1aSopenharmony_ci        }
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_ci        prev_size = out->size;
171cabdff1aSopenharmony_ci
172cabdff1aSopenharmony_ci        ret = av_grow_packet(out, 4 + nalu_size + extra_size);
173cabdff1aSopenharmony_ci        if (ret < 0)
174cabdff1aSopenharmony_ci            goto fail;
175cabdff1aSopenharmony_ci
176cabdff1aSopenharmony_ci        if (extra_size)
177cabdff1aSopenharmony_ci            memcpy(out->data + prev_size, ctx->par_out->extradata, extra_size);
178cabdff1aSopenharmony_ci        AV_WB32(out->data + prev_size + extra_size, 1);
179cabdff1aSopenharmony_ci        bytestream2_get_buffer(&gb, out->data + prev_size + 4 + extra_size, nalu_size);
180cabdff1aSopenharmony_ci    }
181cabdff1aSopenharmony_ci
182cabdff1aSopenharmony_ci    ret = av_packet_copy_props(out, in);
183cabdff1aSopenharmony_ci    if (ret < 0)
184cabdff1aSopenharmony_ci        goto fail;
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_cifail:
187cabdff1aSopenharmony_ci    if (ret < 0)
188cabdff1aSopenharmony_ci        av_packet_unref(out);
189cabdff1aSopenharmony_ci    av_packet_free(&in);
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_ci    return ret;
192cabdff1aSopenharmony_ci}
193cabdff1aSopenharmony_ci
194cabdff1aSopenharmony_cistatic const enum AVCodecID codec_ids[] = {
195cabdff1aSopenharmony_ci    AV_CODEC_ID_HEVC, AV_CODEC_ID_NONE,
196cabdff1aSopenharmony_ci};
197cabdff1aSopenharmony_ci
198cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_hevc_mp4toannexb_bsf = {
199cabdff1aSopenharmony_ci    .p.name         = "hevc_mp4toannexb",
200cabdff1aSopenharmony_ci    .p.codec_ids    = codec_ids,
201cabdff1aSopenharmony_ci    .priv_data_size = sizeof(HEVCBSFContext),
202cabdff1aSopenharmony_ci    .init           = hevc_mp4toannexb_init,
203cabdff1aSopenharmony_ci    .filter         = hevc_mp4toannexb_filter,
204cabdff1aSopenharmony_ci};
205