1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Android MediaCodec MPEG-2 / H.264 / H.265 / MPEG-4 / VP8 / VP9 decoders
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * Copyright (c) 2015-2016 Matthieu Bouron <matthieu.bouron stupeflix.com>
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include "config_components.h"
24cabdff1aSopenharmony_ci
25cabdff1aSopenharmony_ci#include <stdint.h>
26cabdff1aSopenharmony_ci#include <string.h>
27cabdff1aSopenharmony_ci
28cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
29cabdff1aSopenharmony_ci#include "libavutil/common.h"
30cabdff1aSopenharmony_ci#include "libavutil/opt.h"
31cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h"
32cabdff1aSopenharmony_ci#include "libavutil/pixfmt.h"
33cabdff1aSopenharmony_ci#include "libavutil/internal.h"
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_ci#include "avcodec.h"
36cabdff1aSopenharmony_ci#include "codec_internal.h"
37cabdff1aSopenharmony_ci#include "decode.h"
38cabdff1aSopenharmony_ci#include "h264_parse.h"
39cabdff1aSopenharmony_ci#include "h264_ps.h"
40cabdff1aSopenharmony_ci#include "hevc_parse.h"
41cabdff1aSopenharmony_ci#include "hwconfig.h"
42cabdff1aSopenharmony_ci#include "internal.h"
43cabdff1aSopenharmony_ci#include "mediacodec_wrapper.h"
44cabdff1aSopenharmony_ci#include "mediacodecdec_common.h"
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_citypedef struct MediaCodecH264DecContext {
47cabdff1aSopenharmony_ci
48cabdff1aSopenharmony_ci    AVClass *avclass;
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_ci    MediaCodecDecContext *ctx;
51cabdff1aSopenharmony_ci
52cabdff1aSopenharmony_ci    AVPacket buffered_pkt;
53cabdff1aSopenharmony_ci
54cabdff1aSopenharmony_ci    int delay_flush;
55cabdff1aSopenharmony_ci    int amlogic_mpeg2_api23_workaround;
56cabdff1aSopenharmony_ci
57cabdff1aSopenharmony_ci} MediaCodecH264DecContext;
58cabdff1aSopenharmony_ci
59cabdff1aSopenharmony_cistatic av_cold int mediacodec_decode_close(AVCodecContext *avctx)
60cabdff1aSopenharmony_ci{
61cabdff1aSopenharmony_ci    MediaCodecH264DecContext *s = avctx->priv_data;
62cabdff1aSopenharmony_ci
63cabdff1aSopenharmony_ci    ff_mediacodec_dec_close(avctx, s->ctx);
64cabdff1aSopenharmony_ci    s->ctx = NULL;
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci    av_packet_unref(&s->buffered_pkt);
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_ci    return 0;
69cabdff1aSopenharmony_ci}
70cabdff1aSopenharmony_ci
71cabdff1aSopenharmony_ci#if CONFIG_H264_MEDIACODEC_DECODER || CONFIG_HEVC_MEDIACODEC_DECODER
72cabdff1aSopenharmony_cistatic int h2645_ps_to_nalu(const uint8_t *src, int src_size, uint8_t **out, int *out_size)
73cabdff1aSopenharmony_ci{
74cabdff1aSopenharmony_ci    int i;
75cabdff1aSopenharmony_ci    int ret = 0;
76cabdff1aSopenharmony_ci    uint8_t *p = NULL;
77cabdff1aSopenharmony_ci    static const uint8_t nalu_header[] = { 0x00, 0x00, 0x00, 0x01 };
78cabdff1aSopenharmony_ci
79cabdff1aSopenharmony_ci    if (!out || !out_size) {
80cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
81cabdff1aSopenharmony_ci    }
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci    p = av_malloc(sizeof(nalu_header) + src_size);
84cabdff1aSopenharmony_ci    if (!p) {
85cabdff1aSopenharmony_ci        return AVERROR(ENOMEM);
86cabdff1aSopenharmony_ci    }
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_ci    *out = p;
89cabdff1aSopenharmony_ci    *out_size = sizeof(nalu_header) + src_size;
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci    memcpy(p, nalu_header, sizeof(nalu_header));
92cabdff1aSopenharmony_ci    memcpy(p + sizeof(nalu_header), src, src_size);
93cabdff1aSopenharmony_ci
94cabdff1aSopenharmony_ci    /* Escape 0x00, 0x00, 0x0{0-3} pattern */
95cabdff1aSopenharmony_ci    for (i = 4; i < *out_size; i++) {
96cabdff1aSopenharmony_ci        if (i < *out_size - 3 &&
97cabdff1aSopenharmony_ci            p[i + 0] == 0 &&
98cabdff1aSopenharmony_ci            p[i + 1] == 0 &&
99cabdff1aSopenharmony_ci            p[i + 2] <= 3) {
100cabdff1aSopenharmony_ci            uint8_t *new;
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci            *out_size += 1;
103cabdff1aSopenharmony_ci            new = av_realloc(*out, *out_size);
104cabdff1aSopenharmony_ci            if (!new) {
105cabdff1aSopenharmony_ci                ret = AVERROR(ENOMEM);
106cabdff1aSopenharmony_ci                goto done;
107cabdff1aSopenharmony_ci            }
108cabdff1aSopenharmony_ci            *out = p = new;
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci            i = i + 2;
111cabdff1aSopenharmony_ci            memmove(p + i + 1, p + i, *out_size - (i + 1));
112cabdff1aSopenharmony_ci            p[i] = 0x03;
113cabdff1aSopenharmony_ci        }
114cabdff1aSopenharmony_ci    }
115cabdff1aSopenharmony_cidone:
116cabdff1aSopenharmony_ci    if (ret < 0) {
117cabdff1aSopenharmony_ci        av_freep(out);
118cabdff1aSopenharmony_ci        *out_size = 0;
119cabdff1aSopenharmony_ci    }
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    return ret;
122cabdff1aSopenharmony_ci}
123cabdff1aSopenharmony_ci#endif
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci#if CONFIG_H264_MEDIACODEC_DECODER
126cabdff1aSopenharmony_cistatic int h264_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
127cabdff1aSopenharmony_ci{
128cabdff1aSopenharmony_ci    int i;
129cabdff1aSopenharmony_ci    int ret;
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_ci    H264ParamSets ps;
132cabdff1aSopenharmony_ci    const PPS *pps = NULL;
133cabdff1aSopenharmony_ci    const SPS *sps = NULL;
134cabdff1aSopenharmony_ci    int is_avc = 0;
135cabdff1aSopenharmony_ci    int nal_length_size = 0;
136cabdff1aSopenharmony_ci
137cabdff1aSopenharmony_ci    memset(&ps, 0, sizeof(ps));
138cabdff1aSopenharmony_ci
139cabdff1aSopenharmony_ci    ret = ff_h264_decode_extradata(avctx->extradata, avctx->extradata_size,
140cabdff1aSopenharmony_ci                                   &ps, &is_avc, &nal_length_size, 0, avctx);
141cabdff1aSopenharmony_ci    if (ret < 0) {
142cabdff1aSopenharmony_ci        goto done;
143cabdff1aSopenharmony_ci    }
144cabdff1aSopenharmony_ci
145cabdff1aSopenharmony_ci    for (i = 0; i < MAX_PPS_COUNT; i++) {
146cabdff1aSopenharmony_ci        if (ps.pps_list[i]) {
147cabdff1aSopenharmony_ci            pps = (const PPS*)ps.pps_list[i]->data;
148cabdff1aSopenharmony_ci            break;
149cabdff1aSopenharmony_ci        }
150cabdff1aSopenharmony_ci    }
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_ci    if (pps) {
153cabdff1aSopenharmony_ci        if (ps.sps_list[pps->sps_id]) {
154cabdff1aSopenharmony_ci            sps = (const SPS*)ps.sps_list[pps->sps_id]->data;
155cabdff1aSopenharmony_ci        }
156cabdff1aSopenharmony_ci    }
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    if (pps && sps) {
159cabdff1aSopenharmony_ci        uint8_t *data = NULL;
160cabdff1aSopenharmony_ci        int data_size = 0;
161cabdff1aSopenharmony_ci
162cabdff1aSopenharmony_ci        avctx->profile = ff_h264_get_profile(sps);
163cabdff1aSopenharmony_ci        avctx->level = sps->level_idc;
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ci        if ((ret = h2645_ps_to_nalu(sps->data, sps->data_size, &data, &data_size)) < 0) {
166cabdff1aSopenharmony_ci            goto done;
167cabdff1aSopenharmony_ci        }
168cabdff1aSopenharmony_ci        ff_AMediaFormat_setBuffer(format, "csd-0", (void*)data, data_size);
169cabdff1aSopenharmony_ci        av_freep(&data);
170cabdff1aSopenharmony_ci
171cabdff1aSopenharmony_ci        if ((ret = h2645_ps_to_nalu(pps->data, pps->data_size, &data, &data_size)) < 0) {
172cabdff1aSopenharmony_ci            goto done;
173cabdff1aSopenharmony_ci        }
174cabdff1aSopenharmony_ci        ff_AMediaFormat_setBuffer(format, "csd-1", (void*)data, data_size);
175cabdff1aSopenharmony_ci        av_freep(&data);
176cabdff1aSopenharmony_ci    } else {
177cabdff1aSopenharmony_ci        const int warn = is_avc && (avctx->codec_tag == MKTAG('a','v','c','1') ||
178cabdff1aSopenharmony_ci                                    avctx->codec_tag == MKTAG('a','v','c','2'));
179cabdff1aSopenharmony_ci        av_log(avctx, warn ? AV_LOG_WARNING : AV_LOG_DEBUG,
180cabdff1aSopenharmony_ci               "Could not extract PPS/SPS from extradata\n");
181cabdff1aSopenharmony_ci        ret = 0;
182cabdff1aSopenharmony_ci    }
183cabdff1aSopenharmony_ci
184cabdff1aSopenharmony_cidone:
185cabdff1aSopenharmony_ci    ff_h264_ps_uninit(&ps);
186cabdff1aSopenharmony_ci
187cabdff1aSopenharmony_ci    return ret;
188cabdff1aSopenharmony_ci}
189cabdff1aSopenharmony_ci#endif
190cabdff1aSopenharmony_ci
191cabdff1aSopenharmony_ci#if CONFIG_HEVC_MEDIACODEC_DECODER
192cabdff1aSopenharmony_cistatic int hevc_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
193cabdff1aSopenharmony_ci{
194cabdff1aSopenharmony_ci    int i;
195cabdff1aSopenharmony_ci    int ret;
196cabdff1aSopenharmony_ci
197cabdff1aSopenharmony_ci    HEVCParamSets ps;
198cabdff1aSopenharmony_ci    HEVCSEI sei;
199cabdff1aSopenharmony_ci
200cabdff1aSopenharmony_ci    const HEVCVPS *vps = NULL;
201cabdff1aSopenharmony_ci    const HEVCPPS *pps = NULL;
202cabdff1aSopenharmony_ci    const HEVCSPS *sps = NULL;
203cabdff1aSopenharmony_ci    int is_nalff = 0;
204cabdff1aSopenharmony_ci    int nal_length_size = 0;
205cabdff1aSopenharmony_ci
206cabdff1aSopenharmony_ci    uint8_t *vps_data = NULL;
207cabdff1aSopenharmony_ci    uint8_t *sps_data = NULL;
208cabdff1aSopenharmony_ci    uint8_t *pps_data = NULL;
209cabdff1aSopenharmony_ci    int vps_data_size = 0;
210cabdff1aSopenharmony_ci    int sps_data_size = 0;
211cabdff1aSopenharmony_ci    int pps_data_size = 0;
212cabdff1aSopenharmony_ci
213cabdff1aSopenharmony_ci    memset(&ps, 0, sizeof(ps));
214cabdff1aSopenharmony_ci    memset(&sei, 0, sizeof(sei));
215cabdff1aSopenharmony_ci
216cabdff1aSopenharmony_ci    ret = ff_hevc_decode_extradata(avctx->extradata, avctx->extradata_size,
217cabdff1aSopenharmony_ci                                   &ps, &sei, &is_nalff, &nal_length_size, 0, 1, avctx);
218cabdff1aSopenharmony_ci    if (ret < 0) {
219cabdff1aSopenharmony_ci        goto done;
220cabdff1aSopenharmony_ci    }
221cabdff1aSopenharmony_ci
222cabdff1aSopenharmony_ci    for (i = 0; i < HEVC_MAX_VPS_COUNT; i++) {
223cabdff1aSopenharmony_ci        if (ps.vps_list[i]) {
224cabdff1aSopenharmony_ci            vps = (const HEVCVPS*)ps.vps_list[i]->data;
225cabdff1aSopenharmony_ci            break;
226cabdff1aSopenharmony_ci        }
227cabdff1aSopenharmony_ci    }
228cabdff1aSopenharmony_ci
229cabdff1aSopenharmony_ci    for (i = 0; i < HEVC_MAX_PPS_COUNT; i++) {
230cabdff1aSopenharmony_ci        if (ps.pps_list[i]) {
231cabdff1aSopenharmony_ci            pps = (const HEVCPPS*)ps.pps_list[i]->data;
232cabdff1aSopenharmony_ci            break;
233cabdff1aSopenharmony_ci        }
234cabdff1aSopenharmony_ci    }
235cabdff1aSopenharmony_ci
236cabdff1aSopenharmony_ci    if (pps) {
237cabdff1aSopenharmony_ci        if (ps.sps_list[pps->sps_id]) {
238cabdff1aSopenharmony_ci            sps = (const HEVCSPS*)ps.sps_list[pps->sps_id]->data;
239cabdff1aSopenharmony_ci        }
240cabdff1aSopenharmony_ci    }
241cabdff1aSopenharmony_ci
242cabdff1aSopenharmony_ci    if (vps && pps && sps) {
243cabdff1aSopenharmony_ci        uint8_t *data;
244cabdff1aSopenharmony_ci        int data_size;
245cabdff1aSopenharmony_ci
246cabdff1aSopenharmony_ci        avctx->profile = sps->ptl.general_ptl.profile_idc;
247cabdff1aSopenharmony_ci        avctx->level   = sps->ptl.general_ptl.level_idc;
248cabdff1aSopenharmony_ci
249cabdff1aSopenharmony_ci        if ((ret = h2645_ps_to_nalu(vps->data, vps->data_size, &vps_data, &vps_data_size)) < 0 ||
250cabdff1aSopenharmony_ci            (ret = h2645_ps_to_nalu(sps->data, sps->data_size, &sps_data, &sps_data_size)) < 0 ||
251cabdff1aSopenharmony_ci            (ret = h2645_ps_to_nalu(pps->data, pps->data_size, &pps_data, &pps_data_size)) < 0) {
252cabdff1aSopenharmony_ci            goto done;
253cabdff1aSopenharmony_ci        }
254cabdff1aSopenharmony_ci
255cabdff1aSopenharmony_ci        data_size = vps_data_size + sps_data_size + pps_data_size;
256cabdff1aSopenharmony_ci        data = av_mallocz(data_size);
257cabdff1aSopenharmony_ci        if (!data) {
258cabdff1aSopenharmony_ci            ret = AVERROR(ENOMEM);
259cabdff1aSopenharmony_ci            goto done;
260cabdff1aSopenharmony_ci        }
261cabdff1aSopenharmony_ci
262cabdff1aSopenharmony_ci        memcpy(data                                , vps_data, vps_data_size);
263cabdff1aSopenharmony_ci        memcpy(data + vps_data_size                , sps_data, sps_data_size);
264cabdff1aSopenharmony_ci        memcpy(data + vps_data_size + sps_data_size, pps_data, pps_data_size);
265cabdff1aSopenharmony_ci
266cabdff1aSopenharmony_ci        ff_AMediaFormat_setBuffer(format, "csd-0", data, data_size);
267cabdff1aSopenharmony_ci
268cabdff1aSopenharmony_ci        av_freep(&data);
269cabdff1aSopenharmony_ci    } else {
270cabdff1aSopenharmony_ci        const int warn = is_nalff && avctx->codec_tag == MKTAG('h','v','c','1');
271cabdff1aSopenharmony_ci        av_log(avctx, warn ? AV_LOG_WARNING : AV_LOG_DEBUG,
272cabdff1aSopenharmony_ci               "Could not extract VPS/PPS/SPS from extradata\n");
273cabdff1aSopenharmony_ci        ret = 0;
274cabdff1aSopenharmony_ci    }
275cabdff1aSopenharmony_ci
276cabdff1aSopenharmony_cidone:
277cabdff1aSopenharmony_ci    ff_hevc_ps_uninit(&ps);
278cabdff1aSopenharmony_ci
279cabdff1aSopenharmony_ci    av_freep(&vps_data);
280cabdff1aSopenharmony_ci    av_freep(&sps_data);
281cabdff1aSopenharmony_ci    av_freep(&pps_data);
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci    return ret;
284cabdff1aSopenharmony_ci}
285cabdff1aSopenharmony_ci#endif
286cabdff1aSopenharmony_ci
287cabdff1aSopenharmony_ci#if CONFIG_MPEG2_MEDIACODEC_DECODER || \
288cabdff1aSopenharmony_ci    CONFIG_MPEG4_MEDIACODEC_DECODER || \
289cabdff1aSopenharmony_ci    CONFIG_VP8_MEDIACODEC_DECODER   || \
290cabdff1aSopenharmony_ci    CONFIG_VP9_MEDIACODEC_DECODER
291cabdff1aSopenharmony_cistatic int common_set_extradata(AVCodecContext *avctx, FFAMediaFormat *format)
292cabdff1aSopenharmony_ci{
293cabdff1aSopenharmony_ci    int ret = 0;
294cabdff1aSopenharmony_ci
295cabdff1aSopenharmony_ci    if (avctx->extradata) {
296cabdff1aSopenharmony_ci        ff_AMediaFormat_setBuffer(format, "csd-0", avctx->extradata, avctx->extradata_size);
297cabdff1aSopenharmony_ci    }
298cabdff1aSopenharmony_ci
299cabdff1aSopenharmony_ci    return ret;
300cabdff1aSopenharmony_ci}
301cabdff1aSopenharmony_ci#endif
302cabdff1aSopenharmony_ci
303cabdff1aSopenharmony_cistatic av_cold int mediacodec_decode_init(AVCodecContext *avctx)
304cabdff1aSopenharmony_ci{
305cabdff1aSopenharmony_ci    int ret;
306cabdff1aSopenharmony_ci    int sdk_int;
307cabdff1aSopenharmony_ci
308cabdff1aSopenharmony_ci    const char *codec_mime = NULL;
309cabdff1aSopenharmony_ci
310cabdff1aSopenharmony_ci    FFAMediaFormat *format = NULL;
311cabdff1aSopenharmony_ci    MediaCodecH264DecContext *s = avctx->priv_data;
312cabdff1aSopenharmony_ci
313cabdff1aSopenharmony_ci    format = ff_AMediaFormat_new();
314cabdff1aSopenharmony_ci    if (!format) {
315cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to create media format\n");
316cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;
317cabdff1aSopenharmony_ci        goto done;
318cabdff1aSopenharmony_ci    }
319cabdff1aSopenharmony_ci
320cabdff1aSopenharmony_ci    switch (avctx->codec_id) {
321cabdff1aSopenharmony_ci#if CONFIG_H264_MEDIACODEC_DECODER
322cabdff1aSopenharmony_ci    case AV_CODEC_ID_H264:
323cabdff1aSopenharmony_ci        codec_mime = "video/avc";
324cabdff1aSopenharmony_ci
325cabdff1aSopenharmony_ci        ret = h264_set_extradata(avctx, format);
326cabdff1aSopenharmony_ci        if (ret < 0)
327cabdff1aSopenharmony_ci            goto done;
328cabdff1aSopenharmony_ci        break;
329cabdff1aSopenharmony_ci#endif
330cabdff1aSopenharmony_ci#if CONFIG_HEVC_MEDIACODEC_DECODER
331cabdff1aSopenharmony_ci    case AV_CODEC_ID_HEVC:
332cabdff1aSopenharmony_ci        codec_mime = "video/hevc";
333cabdff1aSopenharmony_ci
334cabdff1aSopenharmony_ci        ret = hevc_set_extradata(avctx, format);
335cabdff1aSopenharmony_ci        if (ret < 0)
336cabdff1aSopenharmony_ci            goto done;
337cabdff1aSopenharmony_ci        break;
338cabdff1aSopenharmony_ci#endif
339cabdff1aSopenharmony_ci#if CONFIG_MPEG2_MEDIACODEC_DECODER
340cabdff1aSopenharmony_ci    case AV_CODEC_ID_MPEG2VIDEO:
341cabdff1aSopenharmony_ci        codec_mime = "video/mpeg2";
342cabdff1aSopenharmony_ci
343cabdff1aSopenharmony_ci        ret = common_set_extradata(avctx, format);
344cabdff1aSopenharmony_ci        if (ret < 0)
345cabdff1aSopenharmony_ci            goto done;
346cabdff1aSopenharmony_ci        break;
347cabdff1aSopenharmony_ci#endif
348cabdff1aSopenharmony_ci#if CONFIG_MPEG4_MEDIACODEC_DECODER
349cabdff1aSopenharmony_ci    case AV_CODEC_ID_MPEG4:
350cabdff1aSopenharmony_ci        codec_mime = "video/mp4v-es",
351cabdff1aSopenharmony_ci
352cabdff1aSopenharmony_ci        ret = common_set_extradata(avctx, format);
353cabdff1aSopenharmony_ci        if (ret < 0)
354cabdff1aSopenharmony_ci            goto done;
355cabdff1aSopenharmony_ci        break;
356cabdff1aSopenharmony_ci#endif
357cabdff1aSopenharmony_ci#if CONFIG_VP8_MEDIACODEC_DECODER
358cabdff1aSopenharmony_ci    case AV_CODEC_ID_VP8:
359cabdff1aSopenharmony_ci        codec_mime = "video/x-vnd.on2.vp8";
360cabdff1aSopenharmony_ci
361cabdff1aSopenharmony_ci        ret = common_set_extradata(avctx, format);
362cabdff1aSopenharmony_ci        if (ret < 0)
363cabdff1aSopenharmony_ci            goto done;
364cabdff1aSopenharmony_ci        break;
365cabdff1aSopenharmony_ci#endif
366cabdff1aSopenharmony_ci#if CONFIG_VP9_MEDIACODEC_DECODER
367cabdff1aSopenharmony_ci    case AV_CODEC_ID_VP9:
368cabdff1aSopenharmony_ci        codec_mime = "video/x-vnd.on2.vp9";
369cabdff1aSopenharmony_ci
370cabdff1aSopenharmony_ci        ret = common_set_extradata(avctx, format);
371cabdff1aSopenharmony_ci        if (ret < 0)
372cabdff1aSopenharmony_ci            goto done;
373cabdff1aSopenharmony_ci        break;
374cabdff1aSopenharmony_ci#endif
375cabdff1aSopenharmony_ci    default:
376cabdff1aSopenharmony_ci        av_assert0(0);
377cabdff1aSopenharmony_ci    }
378cabdff1aSopenharmony_ci
379cabdff1aSopenharmony_ci    ff_AMediaFormat_setString(format, "mime", codec_mime);
380cabdff1aSopenharmony_ci    ff_AMediaFormat_setInt32(format, "width", avctx->width);
381cabdff1aSopenharmony_ci    ff_AMediaFormat_setInt32(format, "height", avctx->height);
382cabdff1aSopenharmony_ci
383cabdff1aSopenharmony_ci    s->ctx = av_mallocz(sizeof(*s->ctx));
384cabdff1aSopenharmony_ci    if (!s->ctx) {
385cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to allocate MediaCodecDecContext\n");
386cabdff1aSopenharmony_ci        ret = AVERROR(ENOMEM);
387cabdff1aSopenharmony_ci        goto done;
388cabdff1aSopenharmony_ci    }
389cabdff1aSopenharmony_ci
390cabdff1aSopenharmony_ci    s->ctx->delay_flush = s->delay_flush;
391cabdff1aSopenharmony_ci
392cabdff1aSopenharmony_ci    if ((ret = ff_mediacodec_dec_init(avctx, s->ctx, codec_mime, format)) < 0) {
393cabdff1aSopenharmony_ci        s->ctx = NULL;
394cabdff1aSopenharmony_ci        goto done;
395cabdff1aSopenharmony_ci    }
396cabdff1aSopenharmony_ci
397cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_INFO,
398cabdff1aSopenharmony_ci           "MediaCodec started successfully: codec = %s, ret = %d\n",
399cabdff1aSopenharmony_ci           s->ctx->codec_name, ret);
400cabdff1aSopenharmony_ci
401cabdff1aSopenharmony_ci    sdk_int = ff_Build_SDK_INT(avctx);
402cabdff1aSopenharmony_ci    if (sdk_int <= 23 &&
403cabdff1aSopenharmony_ci        strcmp(s->ctx->codec_name, "OMX.amlogic.mpeg2.decoder.awesome") == 0) {
404cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_INFO, "Enabling workaround for %s on API=%d\n",
405cabdff1aSopenharmony_ci               s->ctx->codec_name, sdk_int);
406cabdff1aSopenharmony_ci        s->amlogic_mpeg2_api23_workaround = 1;
407cabdff1aSopenharmony_ci    }
408cabdff1aSopenharmony_ci
409cabdff1aSopenharmony_cidone:
410cabdff1aSopenharmony_ci    if (format) {
411cabdff1aSopenharmony_ci        ff_AMediaFormat_delete(format);
412cabdff1aSopenharmony_ci    }
413cabdff1aSopenharmony_ci
414cabdff1aSopenharmony_ci    if (ret < 0) {
415cabdff1aSopenharmony_ci        mediacodec_decode_close(avctx);
416cabdff1aSopenharmony_ci    }
417cabdff1aSopenharmony_ci
418cabdff1aSopenharmony_ci    return ret;
419cabdff1aSopenharmony_ci}
420cabdff1aSopenharmony_ci
421cabdff1aSopenharmony_cistatic int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
422cabdff1aSopenharmony_ci{
423cabdff1aSopenharmony_ci    MediaCodecH264DecContext *s = avctx->priv_data;
424cabdff1aSopenharmony_ci    int ret;
425cabdff1aSopenharmony_ci    ssize_t index;
426cabdff1aSopenharmony_ci
427cabdff1aSopenharmony_ci    /* In delay_flush mode, wait until the user has released or rendered
428cabdff1aSopenharmony_ci       all retained frames. */
429cabdff1aSopenharmony_ci    if (s->delay_flush && ff_mediacodec_dec_is_flushing(avctx, s->ctx)) {
430cabdff1aSopenharmony_ci        if (!ff_mediacodec_dec_flush(avctx, s->ctx)) {
431cabdff1aSopenharmony_ci            return AVERROR(EAGAIN);
432cabdff1aSopenharmony_ci        }
433cabdff1aSopenharmony_ci    }
434cabdff1aSopenharmony_ci
435cabdff1aSopenharmony_ci    /* poll for new frame */
436cabdff1aSopenharmony_ci    ret = ff_mediacodec_dec_receive(avctx, s->ctx, frame, false);
437cabdff1aSopenharmony_ci    if (ret != AVERROR(EAGAIN))
438cabdff1aSopenharmony_ci        return ret;
439cabdff1aSopenharmony_ci
440cabdff1aSopenharmony_ci    /* feed decoder */
441cabdff1aSopenharmony_ci    while (1) {
442cabdff1aSopenharmony_ci        if (s->ctx->current_input_buffer < 0) {
443cabdff1aSopenharmony_ci            /* poll for input space */
444cabdff1aSopenharmony_ci            index = ff_AMediaCodec_dequeueInputBuffer(s->ctx->codec, 0);
445cabdff1aSopenharmony_ci            if (index < 0) {
446cabdff1aSopenharmony_ci                /* no space, block for an output frame to appear */
447cabdff1aSopenharmony_ci                return ff_mediacodec_dec_receive(avctx, s->ctx, frame, true);
448cabdff1aSopenharmony_ci            }
449cabdff1aSopenharmony_ci            s->ctx->current_input_buffer = index;
450cabdff1aSopenharmony_ci        }
451cabdff1aSopenharmony_ci
452cabdff1aSopenharmony_ci        /* try to flush any buffered packet data */
453cabdff1aSopenharmony_ci        if (s->buffered_pkt.size > 0) {
454cabdff1aSopenharmony_ci            ret = ff_mediacodec_dec_send(avctx, s->ctx, &s->buffered_pkt, false);
455cabdff1aSopenharmony_ci            if (ret >= 0) {
456cabdff1aSopenharmony_ci                s->buffered_pkt.size -= ret;
457cabdff1aSopenharmony_ci                s->buffered_pkt.data += ret;
458cabdff1aSopenharmony_ci                if (s->buffered_pkt.size <= 0) {
459cabdff1aSopenharmony_ci                    av_packet_unref(&s->buffered_pkt);
460cabdff1aSopenharmony_ci                } else {
461cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_WARNING,
462cabdff1aSopenharmony_ci                           "could not send entire packet in single input buffer (%d < %d)\n",
463cabdff1aSopenharmony_ci                           ret, s->buffered_pkt.size+ret);
464cabdff1aSopenharmony_ci                }
465cabdff1aSopenharmony_ci            } else if (ret < 0 && ret != AVERROR(EAGAIN)) {
466cabdff1aSopenharmony_ci                return ret;
467cabdff1aSopenharmony_ci            }
468cabdff1aSopenharmony_ci
469cabdff1aSopenharmony_ci            if (s->amlogic_mpeg2_api23_workaround && s->buffered_pkt.size <= 0) {
470cabdff1aSopenharmony_ci                /* fallthrough to fetch next packet regardless of input buffer space */
471cabdff1aSopenharmony_ci            } else {
472cabdff1aSopenharmony_ci                /* poll for space again */
473cabdff1aSopenharmony_ci                continue;
474cabdff1aSopenharmony_ci            }
475cabdff1aSopenharmony_ci        }
476cabdff1aSopenharmony_ci
477cabdff1aSopenharmony_ci        /* fetch new packet or eof */
478cabdff1aSopenharmony_ci        ret = ff_decode_get_packet(avctx, &s->buffered_pkt);
479cabdff1aSopenharmony_ci        if (ret == AVERROR_EOF) {
480cabdff1aSopenharmony_ci            AVPacket null_pkt = { 0 };
481cabdff1aSopenharmony_ci            ret = ff_mediacodec_dec_send(avctx, s->ctx, &null_pkt, true);
482cabdff1aSopenharmony_ci            if (ret < 0)
483cabdff1aSopenharmony_ci                return ret;
484cabdff1aSopenharmony_ci            return ff_mediacodec_dec_receive(avctx, s->ctx, frame, true);
485cabdff1aSopenharmony_ci        } else if (ret == AVERROR(EAGAIN) && s->ctx->current_input_buffer < 0) {
486cabdff1aSopenharmony_ci            return ff_mediacodec_dec_receive(avctx, s->ctx, frame, true);
487cabdff1aSopenharmony_ci        } else if (ret < 0) {
488cabdff1aSopenharmony_ci            return ret;
489cabdff1aSopenharmony_ci        }
490cabdff1aSopenharmony_ci    }
491cabdff1aSopenharmony_ci
492cabdff1aSopenharmony_ci    return AVERROR(EAGAIN);
493cabdff1aSopenharmony_ci}
494cabdff1aSopenharmony_ci
495cabdff1aSopenharmony_cistatic void mediacodec_decode_flush(AVCodecContext *avctx)
496cabdff1aSopenharmony_ci{
497cabdff1aSopenharmony_ci    MediaCodecH264DecContext *s = avctx->priv_data;
498cabdff1aSopenharmony_ci
499cabdff1aSopenharmony_ci    av_packet_unref(&s->buffered_pkt);
500cabdff1aSopenharmony_ci
501cabdff1aSopenharmony_ci    ff_mediacodec_dec_flush(avctx, s->ctx);
502cabdff1aSopenharmony_ci}
503cabdff1aSopenharmony_ci
504cabdff1aSopenharmony_cistatic const AVCodecHWConfigInternal *const mediacodec_hw_configs[] = {
505cabdff1aSopenharmony_ci    &(const AVCodecHWConfigInternal) {
506cabdff1aSopenharmony_ci        .public          = {
507cabdff1aSopenharmony_ci            .pix_fmt     = AV_PIX_FMT_MEDIACODEC,
508cabdff1aSopenharmony_ci            .methods     = AV_CODEC_HW_CONFIG_METHOD_AD_HOC |
509cabdff1aSopenharmony_ci                           AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX,
510cabdff1aSopenharmony_ci            .device_type = AV_HWDEVICE_TYPE_MEDIACODEC,
511cabdff1aSopenharmony_ci        },
512cabdff1aSopenharmony_ci        .hwaccel         = NULL,
513cabdff1aSopenharmony_ci    },
514cabdff1aSopenharmony_ci    NULL
515cabdff1aSopenharmony_ci};
516cabdff1aSopenharmony_ci
517cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(MediaCodecH264DecContext, x)
518cabdff1aSopenharmony_ci#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
519cabdff1aSopenharmony_cistatic const AVOption ff_mediacodec_vdec_options[] = {
520cabdff1aSopenharmony_ci    { "delay_flush", "Delay flush until hw output buffers are returned to the decoder",
521cabdff1aSopenharmony_ci                     OFFSET(delay_flush), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VD },
522cabdff1aSopenharmony_ci    { NULL }
523cabdff1aSopenharmony_ci};
524cabdff1aSopenharmony_ci
525cabdff1aSopenharmony_ci#define DECLARE_MEDIACODEC_VCLASS(short_name)                   \
526cabdff1aSopenharmony_cistatic const AVClass ff_##short_name##_mediacodec_dec_class = { \
527cabdff1aSopenharmony_ci    .class_name = #short_name "_mediacodec",                    \
528cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,                         \
529cabdff1aSopenharmony_ci    .option     = ff_mediacodec_vdec_options,                   \
530cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,                        \
531cabdff1aSopenharmony_ci};
532cabdff1aSopenharmony_ci
533cabdff1aSopenharmony_ci#define DECLARE_MEDIACODEC_VDEC(short_name, full_name, codec_id, bsf)                          \
534cabdff1aSopenharmony_ciDECLARE_MEDIACODEC_VCLASS(short_name)                                                          \
535cabdff1aSopenharmony_ciconst FFCodec ff_ ## short_name ## _mediacodec_decoder = {                                     \
536cabdff1aSopenharmony_ci    .p.name         = #short_name "_mediacodec",                                               \
537cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL(full_name " Android MediaCodec decoder"),           \
538cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,                                                      \
539cabdff1aSopenharmony_ci    .p.id           = codec_id,                                                                \
540cabdff1aSopenharmony_ci    .p.priv_class   = &ff_##short_name##_mediacodec_dec_class,                                 \
541cabdff1aSopenharmony_ci    .priv_data_size = sizeof(MediaCodecH264DecContext),                                        \
542cabdff1aSopenharmony_ci    .init           = mediacodec_decode_init,                                                  \
543cabdff1aSopenharmony_ci    FF_CODEC_RECEIVE_FRAME_CB(mediacodec_receive_frame),                                       \
544cabdff1aSopenharmony_ci    .flush          = mediacodec_decode_flush,                                                 \
545cabdff1aSopenharmony_ci    .close          = mediacodec_decode_close,                                                 \
546cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE, \
547cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_SETS_PKT_DTS,                                               \
548cabdff1aSopenharmony_ci    .bsfs           = bsf,                                                                     \
549cabdff1aSopenharmony_ci    .hw_configs     = mediacodec_hw_configs,                                                   \
550cabdff1aSopenharmony_ci    .p.wrapper_name = "mediacodec",                                                            \
551cabdff1aSopenharmony_ci};                                                                                             \
552cabdff1aSopenharmony_ci
553cabdff1aSopenharmony_ci#if CONFIG_H264_MEDIACODEC_DECODER
554cabdff1aSopenharmony_ciDECLARE_MEDIACODEC_VDEC(h264, "H.264", AV_CODEC_ID_H264, "h264_mp4toannexb")
555cabdff1aSopenharmony_ci#endif
556cabdff1aSopenharmony_ci
557cabdff1aSopenharmony_ci#if CONFIG_HEVC_MEDIACODEC_DECODER
558cabdff1aSopenharmony_ciDECLARE_MEDIACODEC_VDEC(hevc, "H.265", AV_CODEC_ID_HEVC, "hevc_mp4toannexb")
559cabdff1aSopenharmony_ci#endif
560cabdff1aSopenharmony_ci
561cabdff1aSopenharmony_ci#if CONFIG_MPEG2_MEDIACODEC_DECODER
562cabdff1aSopenharmony_ciDECLARE_MEDIACODEC_VDEC(mpeg2, "MPEG-2", AV_CODEC_ID_MPEG2VIDEO, NULL)
563cabdff1aSopenharmony_ci#endif
564cabdff1aSopenharmony_ci
565cabdff1aSopenharmony_ci#if CONFIG_MPEG4_MEDIACODEC_DECODER
566cabdff1aSopenharmony_ciDECLARE_MEDIACODEC_VDEC(mpeg4, "MPEG-4", AV_CODEC_ID_MPEG4, NULL)
567cabdff1aSopenharmony_ci#endif
568cabdff1aSopenharmony_ci
569cabdff1aSopenharmony_ci#if CONFIG_VP8_MEDIACODEC_DECODER
570cabdff1aSopenharmony_ciDECLARE_MEDIACODEC_VDEC(vp8, "VP8", AV_CODEC_ID_VP8, NULL)
571cabdff1aSopenharmony_ci#endif
572cabdff1aSopenharmony_ci
573cabdff1aSopenharmony_ci#if CONFIG_VP9_MEDIACODEC_DECODER
574cabdff1aSopenharmony_ciDECLARE_MEDIACODEC_VDEC(vp9, "VP9", AV_CODEC_ID_VP9, NULL)
575cabdff1aSopenharmony_ci#endif
576