1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Android MediaCodec decoder
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 <string.h>
24cabdff1aSopenharmony_ci#include <sys/types.h>
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#include "libavutil/common.h"
27cabdff1aSopenharmony_ci#include "libavutil/hwcontext_mediacodec.h"
28cabdff1aSopenharmony_ci#include "libavutil/mem.h"
29cabdff1aSopenharmony_ci#include "libavutil/log.h"
30cabdff1aSopenharmony_ci#include "libavutil/pixfmt.h"
31cabdff1aSopenharmony_ci#include "libavutil/time.h"
32cabdff1aSopenharmony_ci#include "libavutil/timestamp.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci#include "avcodec.h"
35cabdff1aSopenharmony_ci#include "internal.h"
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci#include "mediacodec.h"
38cabdff1aSopenharmony_ci#include "mediacodec_surface.h"
39cabdff1aSopenharmony_ci#include "mediacodec_sw_buffer.h"
40cabdff1aSopenharmony_ci#include "mediacodec_wrapper.h"
41cabdff1aSopenharmony_ci#include "mediacodecdec_common.h"
42cabdff1aSopenharmony_ci
43cabdff1aSopenharmony_ci/**
44cabdff1aSopenharmony_ci * OMX.k3.video.decoder.avc, OMX.NVIDIA.* OMX.SEC.avc.dec and OMX.google
45cabdff1aSopenharmony_ci * codec workarounds used in various place are taken from the Gstreamer
46cabdff1aSopenharmony_ci * project.
47cabdff1aSopenharmony_ci *
48cabdff1aSopenharmony_ci * Gstreamer references:
49cabdff1aSopenharmony_ci * https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/tree/sys/androidmedia/
50cabdff1aSopenharmony_ci *
51cabdff1aSopenharmony_ci * Gstreamer copyright notice:
52cabdff1aSopenharmony_ci *
53cabdff1aSopenharmony_ci * Copyright (C) 2012, Collabora Ltd.
54cabdff1aSopenharmony_ci *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
55cabdff1aSopenharmony_ci *
56cabdff1aSopenharmony_ci * Copyright (C) 2012, Rafaël Carré <funman@videolanorg>
57cabdff1aSopenharmony_ci *
58cabdff1aSopenharmony_ci * Copyright (C) 2015, Sebastian Dröge <sebastian@centricular.com>
59cabdff1aSopenharmony_ci *
60cabdff1aSopenharmony_ci * Copyright (C) 2014-2015, Collabora Ltd.
61cabdff1aSopenharmony_ci *   Author: Matthieu Bouron <matthieu.bouron@gcollabora.com>
62cabdff1aSopenharmony_ci *
63cabdff1aSopenharmony_ci * Copyright (C) 2015, Edward Hervey
64cabdff1aSopenharmony_ci *   Author: Edward Hervey <bilboed@gmail.com>
65cabdff1aSopenharmony_ci *
66cabdff1aSopenharmony_ci * Copyright (C) 2015, Matthew Waters <matthew@centricular.com>
67cabdff1aSopenharmony_ci *
68cabdff1aSopenharmony_ci * This library is free software; you can redistribute it and/or
69cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
70cabdff1aSopenharmony_ci * License as published by the Free Software Foundation
71cabdff1aSopenharmony_ci * version 2.1 of the License.
72cabdff1aSopenharmony_ci *
73cabdff1aSopenharmony_ci * This library is distributed in the hope that it will be useful,
74cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
75cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
76cabdff1aSopenharmony_ci * Lesser General Public License for more details.
77cabdff1aSopenharmony_ci *
78cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
79cabdff1aSopenharmony_ci * License along with this library; if not, write to the Free Software
80cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
81cabdff1aSopenharmony_ci *
82cabdff1aSopenharmony_ci */
83cabdff1aSopenharmony_ci
84cabdff1aSopenharmony_ci#define INPUT_DEQUEUE_TIMEOUT_US 8000
85cabdff1aSopenharmony_ci#define OUTPUT_DEQUEUE_TIMEOUT_US 8000
86cabdff1aSopenharmony_ci#define OUTPUT_DEQUEUE_BLOCK_TIMEOUT_US 1000000
87cabdff1aSopenharmony_ci
88cabdff1aSopenharmony_cienum {
89cabdff1aSopenharmony_ci    COLOR_RANGE_FULL    = 0x1,
90cabdff1aSopenharmony_ci    COLOR_RANGE_LIMITED = 0x2,
91cabdff1aSopenharmony_ci};
92cabdff1aSopenharmony_ci
93cabdff1aSopenharmony_cistatic enum AVColorRange mcdec_get_color_range(int color_range)
94cabdff1aSopenharmony_ci{
95cabdff1aSopenharmony_ci    switch (color_range) {
96cabdff1aSopenharmony_ci    case COLOR_RANGE_FULL:
97cabdff1aSopenharmony_ci        return AVCOL_RANGE_JPEG;
98cabdff1aSopenharmony_ci    case COLOR_RANGE_LIMITED:
99cabdff1aSopenharmony_ci        return AVCOL_RANGE_MPEG;
100cabdff1aSopenharmony_ci    default:
101cabdff1aSopenharmony_ci        return AVCOL_RANGE_UNSPECIFIED;
102cabdff1aSopenharmony_ci    }
103cabdff1aSopenharmony_ci}
104cabdff1aSopenharmony_ci
105cabdff1aSopenharmony_cienum {
106cabdff1aSopenharmony_ci    COLOR_STANDARD_BT709      = 0x1,
107cabdff1aSopenharmony_ci    COLOR_STANDARD_BT601_PAL  = 0x2,
108cabdff1aSopenharmony_ci    COLOR_STANDARD_BT601_NTSC = 0x4,
109cabdff1aSopenharmony_ci    COLOR_STANDARD_BT2020     = 0x6,
110cabdff1aSopenharmony_ci};
111cabdff1aSopenharmony_ci
112cabdff1aSopenharmony_cistatic enum AVColorSpace mcdec_get_color_space(int color_standard)
113cabdff1aSopenharmony_ci{
114cabdff1aSopenharmony_ci    switch (color_standard) {
115cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT709:
116cabdff1aSopenharmony_ci        return AVCOL_SPC_BT709;
117cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT601_PAL:
118cabdff1aSopenharmony_ci        return AVCOL_SPC_BT470BG;
119cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT601_NTSC:
120cabdff1aSopenharmony_ci        return AVCOL_SPC_SMPTE170M;
121cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT2020:
122cabdff1aSopenharmony_ci        return AVCOL_SPC_BT2020_NCL;
123cabdff1aSopenharmony_ci    default:
124cabdff1aSopenharmony_ci        return AVCOL_SPC_UNSPECIFIED;
125cabdff1aSopenharmony_ci    }
126cabdff1aSopenharmony_ci}
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_cistatic enum AVColorPrimaries mcdec_get_color_pri(int color_standard)
129cabdff1aSopenharmony_ci{
130cabdff1aSopenharmony_ci    switch (color_standard) {
131cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT709:
132cabdff1aSopenharmony_ci        return AVCOL_PRI_BT709;
133cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT601_PAL:
134cabdff1aSopenharmony_ci        return AVCOL_PRI_BT470BG;
135cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT601_NTSC:
136cabdff1aSopenharmony_ci        return AVCOL_PRI_SMPTE170M;
137cabdff1aSopenharmony_ci    case COLOR_STANDARD_BT2020:
138cabdff1aSopenharmony_ci        return AVCOL_PRI_BT2020;
139cabdff1aSopenharmony_ci    default:
140cabdff1aSopenharmony_ci        return AVCOL_PRI_UNSPECIFIED;
141cabdff1aSopenharmony_ci    }
142cabdff1aSopenharmony_ci}
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_cienum {
145cabdff1aSopenharmony_ci    COLOR_TRANSFER_LINEAR    = 0x1,
146cabdff1aSopenharmony_ci    COLOR_TRANSFER_SDR_VIDEO = 0x3,
147cabdff1aSopenharmony_ci    COLOR_TRANSFER_ST2084    = 0x6,
148cabdff1aSopenharmony_ci    COLOR_TRANSFER_HLG       = 0x7,
149cabdff1aSopenharmony_ci};
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_cistatic enum AVColorTransferCharacteristic mcdec_get_color_trc(int color_transfer)
152cabdff1aSopenharmony_ci{
153cabdff1aSopenharmony_ci    switch (color_transfer) {
154cabdff1aSopenharmony_ci    case COLOR_TRANSFER_LINEAR:
155cabdff1aSopenharmony_ci        return AVCOL_TRC_LINEAR;
156cabdff1aSopenharmony_ci    case COLOR_TRANSFER_SDR_VIDEO:
157cabdff1aSopenharmony_ci        return AVCOL_TRC_SMPTE170M;
158cabdff1aSopenharmony_ci    case COLOR_TRANSFER_ST2084:
159cabdff1aSopenharmony_ci        return AVCOL_TRC_SMPTEST2084;
160cabdff1aSopenharmony_ci    case COLOR_TRANSFER_HLG:
161cabdff1aSopenharmony_ci        return AVCOL_TRC_ARIB_STD_B67;
162cabdff1aSopenharmony_ci    default:
163cabdff1aSopenharmony_ci        return AVCOL_TRC_UNSPECIFIED;
164cabdff1aSopenharmony_ci    }
165cabdff1aSopenharmony_ci}
166cabdff1aSopenharmony_ci
167cabdff1aSopenharmony_cienum {
168cabdff1aSopenharmony_ci    COLOR_FormatYUV420Planar                              = 0x13,
169cabdff1aSopenharmony_ci    COLOR_FormatYUV420SemiPlanar                          = 0x15,
170cabdff1aSopenharmony_ci    COLOR_FormatYCbYCr                                    = 0x19,
171cabdff1aSopenharmony_ci    COLOR_FormatAndroidOpaque                             = 0x7F000789,
172cabdff1aSopenharmony_ci    COLOR_QCOM_FormatYUV420SemiPlanar                     = 0x7fa30c00,
173cabdff1aSopenharmony_ci    COLOR_QCOM_FormatYUV420SemiPlanar32m                  = 0x7fa30c04,
174cabdff1aSopenharmony_ci    COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka = 0x7fa30c03,
175cabdff1aSopenharmony_ci    COLOR_TI_FormatYUV420PackedSemiPlanar                 = 0x7f000100,
176cabdff1aSopenharmony_ci    COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced       = 0x7f000001,
177cabdff1aSopenharmony_ci};
178cabdff1aSopenharmony_ci
179cabdff1aSopenharmony_cistatic const struct {
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci    int color_format;
182cabdff1aSopenharmony_ci    enum AVPixelFormat pix_fmt;
183cabdff1aSopenharmony_ci
184cabdff1aSopenharmony_ci} color_formats[] = {
185cabdff1aSopenharmony_ci
186cabdff1aSopenharmony_ci    { COLOR_FormatYUV420Planar,                              AV_PIX_FMT_YUV420P },
187cabdff1aSopenharmony_ci    { COLOR_FormatYUV420SemiPlanar,                          AV_PIX_FMT_NV12    },
188cabdff1aSopenharmony_ci    { COLOR_QCOM_FormatYUV420SemiPlanar,                     AV_PIX_FMT_NV12    },
189cabdff1aSopenharmony_ci    { COLOR_QCOM_FormatYUV420SemiPlanar32m,                  AV_PIX_FMT_NV12    },
190cabdff1aSopenharmony_ci    { COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka, AV_PIX_FMT_NV12    },
191cabdff1aSopenharmony_ci    { COLOR_TI_FormatYUV420PackedSemiPlanar,                 AV_PIX_FMT_NV12    },
192cabdff1aSopenharmony_ci    { COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced,       AV_PIX_FMT_NV12    },
193cabdff1aSopenharmony_ci    { 0 }
194cabdff1aSopenharmony_ci};
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_cistatic enum AVPixelFormat mcdec_map_color_format(AVCodecContext *avctx,
197cabdff1aSopenharmony_ci                                                 MediaCodecDecContext *s,
198cabdff1aSopenharmony_ci                                                 int color_format)
199cabdff1aSopenharmony_ci{
200cabdff1aSopenharmony_ci    int i;
201cabdff1aSopenharmony_ci    enum AVPixelFormat ret = AV_PIX_FMT_NONE;
202cabdff1aSopenharmony_ci
203cabdff1aSopenharmony_ci    if (s->surface) {
204cabdff1aSopenharmony_ci        return AV_PIX_FMT_MEDIACODEC;
205cabdff1aSopenharmony_ci    }
206cabdff1aSopenharmony_ci
207cabdff1aSopenharmony_ci    if (!strcmp(s->codec_name, "OMX.k3.video.decoder.avc") && color_format == COLOR_FormatYCbYCr) {
208cabdff1aSopenharmony_ci        s->color_format = color_format = COLOR_TI_FormatYUV420PackedSemiPlanar;
209cabdff1aSopenharmony_ci    }
210cabdff1aSopenharmony_ci
211cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(color_formats); i++) {
212cabdff1aSopenharmony_ci        if (color_formats[i].color_format == color_format) {
213cabdff1aSopenharmony_ci            return color_formats[i].pix_fmt;
214cabdff1aSopenharmony_ci        }
215cabdff1aSopenharmony_ci    }
216cabdff1aSopenharmony_ci
217cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_ERROR, "Output color format 0x%x (value=%d) is not supported\n",
218cabdff1aSopenharmony_ci        color_format, color_format);
219cabdff1aSopenharmony_ci
220cabdff1aSopenharmony_ci    return ret;
221cabdff1aSopenharmony_ci}
222cabdff1aSopenharmony_ci
223cabdff1aSopenharmony_cistatic void ff_mediacodec_dec_ref(MediaCodecDecContext *s)
224cabdff1aSopenharmony_ci{
225cabdff1aSopenharmony_ci    atomic_fetch_add(&s->refcount, 1);
226cabdff1aSopenharmony_ci}
227cabdff1aSopenharmony_ci
228cabdff1aSopenharmony_cistatic void ff_mediacodec_dec_unref(MediaCodecDecContext *s)
229cabdff1aSopenharmony_ci{
230cabdff1aSopenharmony_ci    if (!s)
231cabdff1aSopenharmony_ci        return;
232cabdff1aSopenharmony_ci
233cabdff1aSopenharmony_ci    if (atomic_fetch_sub(&s->refcount, 1) == 1) {
234cabdff1aSopenharmony_ci        if (s->codec) {
235cabdff1aSopenharmony_ci            ff_AMediaCodec_delete(s->codec);
236cabdff1aSopenharmony_ci            s->codec = NULL;
237cabdff1aSopenharmony_ci        }
238cabdff1aSopenharmony_ci
239cabdff1aSopenharmony_ci        if (s->format) {
240cabdff1aSopenharmony_ci            ff_AMediaFormat_delete(s->format);
241cabdff1aSopenharmony_ci            s->format = NULL;
242cabdff1aSopenharmony_ci        }
243cabdff1aSopenharmony_ci
244cabdff1aSopenharmony_ci        if (s->surface) {
245cabdff1aSopenharmony_ci            ff_mediacodec_surface_unref(s->surface, NULL);
246cabdff1aSopenharmony_ci            s->surface = NULL;
247cabdff1aSopenharmony_ci        }
248cabdff1aSopenharmony_ci
249cabdff1aSopenharmony_ci        av_freep(&s->codec_name);
250cabdff1aSopenharmony_ci        av_freep(&s);
251cabdff1aSopenharmony_ci    }
252cabdff1aSopenharmony_ci}
253cabdff1aSopenharmony_ci
254cabdff1aSopenharmony_cistatic void mediacodec_buffer_release(void *opaque, uint8_t *data)
255cabdff1aSopenharmony_ci{
256cabdff1aSopenharmony_ci    AVMediaCodecBuffer *buffer = opaque;
257cabdff1aSopenharmony_ci    MediaCodecDecContext *ctx = buffer->ctx;
258cabdff1aSopenharmony_ci    int released = atomic_load(&buffer->released);
259cabdff1aSopenharmony_ci
260cabdff1aSopenharmony_ci    if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) {
261cabdff1aSopenharmony_ci        atomic_fetch_sub(&ctx->hw_buffer_count, 1);
262cabdff1aSopenharmony_ci        av_log(ctx->avctx, AV_LOG_DEBUG,
263cabdff1aSopenharmony_ci               "Releasing output buffer %zd (%p) ts=%"PRId64" on free() [%d pending]\n",
264cabdff1aSopenharmony_ci               buffer->index, buffer, buffer->pts, atomic_load(&ctx->hw_buffer_count));
265cabdff1aSopenharmony_ci        ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, 0);
266cabdff1aSopenharmony_ci    }
267cabdff1aSopenharmony_ci
268cabdff1aSopenharmony_ci    if (ctx->delay_flush)
269cabdff1aSopenharmony_ci        ff_mediacodec_dec_unref(ctx);
270cabdff1aSopenharmony_ci    av_freep(&buffer);
271cabdff1aSopenharmony_ci}
272cabdff1aSopenharmony_ci
273cabdff1aSopenharmony_cistatic int mediacodec_wrap_hw_buffer(AVCodecContext *avctx,
274cabdff1aSopenharmony_ci                                  MediaCodecDecContext *s,
275cabdff1aSopenharmony_ci                                  ssize_t index,
276cabdff1aSopenharmony_ci                                  FFAMediaCodecBufferInfo *info,
277cabdff1aSopenharmony_ci                                  AVFrame *frame)
278cabdff1aSopenharmony_ci{
279cabdff1aSopenharmony_ci    int ret = 0;
280cabdff1aSopenharmony_ci    int status = 0;
281cabdff1aSopenharmony_ci    AVMediaCodecBuffer *buffer = NULL;
282cabdff1aSopenharmony_ci
283cabdff1aSopenharmony_ci    frame->buf[0] = NULL;
284cabdff1aSopenharmony_ci    frame->width = avctx->width;
285cabdff1aSopenharmony_ci    frame->height = avctx->height;
286cabdff1aSopenharmony_ci    frame->format = avctx->pix_fmt;
287cabdff1aSopenharmony_ci    frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
288cabdff1aSopenharmony_ci
289cabdff1aSopenharmony_ci    if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
290cabdff1aSopenharmony_ci        frame->pts = av_rescale_q(info->presentationTimeUs,
291cabdff1aSopenharmony_ci                                      AV_TIME_BASE_Q,
292cabdff1aSopenharmony_ci                                      avctx->pkt_timebase);
293cabdff1aSopenharmony_ci    } else {
294cabdff1aSopenharmony_ci        frame->pts = info->presentationTimeUs;
295cabdff1aSopenharmony_ci    }
296cabdff1aSopenharmony_ci    frame->pkt_dts = AV_NOPTS_VALUE;
297cabdff1aSopenharmony_ci    frame->color_range = avctx->color_range;
298cabdff1aSopenharmony_ci    frame->color_primaries = avctx->color_primaries;
299cabdff1aSopenharmony_ci    frame->color_trc = avctx->color_trc;
300cabdff1aSopenharmony_ci    frame->colorspace = avctx->colorspace;
301cabdff1aSopenharmony_ci
302cabdff1aSopenharmony_ci    buffer = av_mallocz(sizeof(AVMediaCodecBuffer));
303cabdff1aSopenharmony_ci    if (!buffer) {
304cabdff1aSopenharmony_ci        ret = AVERROR(ENOMEM);
305cabdff1aSopenharmony_ci        goto fail;
306cabdff1aSopenharmony_ci    }
307cabdff1aSopenharmony_ci
308cabdff1aSopenharmony_ci    atomic_init(&buffer->released, 0);
309cabdff1aSopenharmony_ci
310cabdff1aSopenharmony_ci    frame->buf[0] = av_buffer_create(NULL,
311cabdff1aSopenharmony_ci                                     0,
312cabdff1aSopenharmony_ci                                     mediacodec_buffer_release,
313cabdff1aSopenharmony_ci                                     buffer,
314cabdff1aSopenharmony_ci                                     AV_BUFFER_FLAG_READONLY);
315cabdff1aSopenharmony_ci
316cabdff1aSopenharmony_ci    if (!frame->buf[0]) {
317cabdff1aSopenharmony_ci        ret = AVERROR(ENOMEM);
318cabdff1aSopenharmony_ci        goto fail;
319cabdff1aSopenharmony_ci
320cabdff1aSopenharmony_ci    }
321cabdff1aSopenharmony_ci
322cabdff1aSopenharmony_ci    buffer->ctx = s;
323cabdff1aSopenharmony_ci    buffer->serial = atomic_load(&s->serial);
324cabdff1aSopenharmony_ci    if (s->delay_flush)
325cabdff1aSopenharmony_ci        ff_mediacodec_dec_ref(s);
326cabdff1aSopenharmony_ci
327cabdff1aSopenharmony_ci    buffer->index = index;
328cabdff1aSopenharmony_ci    buffer->pts = info->presentationTimeUs;
329cabdff1aSopenharmony_ci
330cabdff1aSopenharmony_ci    frame->data[3] = (uint8_t *)buffer;
331cabdff1aSopenharmony_ci
332cabdff1aSopenharmony_ci    atomic_fetch_add(&s->hw_buffer_count, 1);
333cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_DEBUG,
334cabdff1aSopenharmony_ci            "Wrapping output buffer %zd (%p) ts=%"PRId64" [%d pending]\n",
335cabdff1aSopenharmony_ci            buffer->index, buffer, buffer->pts, atomic_load(&s->hw_buffer_count));
336cabdff1aSopenharmony_ci
337cabdff1aSopenharmony_ci    return 0;
338cabdff1aSopenharmony_cifail:
339cabdff1aSopenharmony_ci    av_freep(buffer);
340cabdff1aSopenharmony_ci    av_buffer_unref(&frame->buf[0]);
341cabdff1aSopenharmony_ci    status = ff_AMediaCodec_releaseOutputBuffer(s->codec, index, 0);
342cabdff1aSopenharmony_ci    if (status < 0) {
343cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to release output buffer\n");
344cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;
345cabdff1aSopenharmony_ci    }
346cabdff1aSopenharmony_ci
347cabdff1aSopenharmony_ci    return ret;
348cabdff1aSopenharmony_ci}
349cabdff1aSopenharmony_ci
350cabdff1aSopenharmony_cistatic int mediacodec_wrap_sw_buffer(AVCodecContext *avctx,
351cabdff1aSopenharmony_ci                                  MediaCodecDecContext *s,
352cabdff1aSopenharmony_ci                                  uint8_t *data,
353cabdff1aSopenharmony_ci                                  size_t size,
354cabdff1aSopenharmony_ci                                  ssize_t index,
355cabdff1aSopenharmony_ci                                  FFAMediaCodecBufferInfo *info,
356cabdff1aSopenharmony_ci                                  AVFrame *frame)
357cabdff1aSopenharmony_ci{
358cabdff1aSopenharmony_ci    int ret = 0;
359cabdff1aSopenharmony_ci    int status = 0;
360cabdff1aSopenharmony_ci
361cabdff1aSopenharmony_ci    frame->width = avctx->width;
362cabdff1aSopenharmony_ci    frame->height = avctx->height;
363cabdff1aSopenharmony_ci    frame->format = avctx->pix_fmt;
364cabdff1aSopenharmony_ci
365cabdff1aSopenharmony_ci    /* MediaCodec buffers needs to be copied to our own refcounted buffers
366cabdff1aSopenharmony_ci     * because the flush command invalidates all input and output buffers.
367cabdff1aSopenharmony_ci     */
368cabdff1aSopenharmony_ci    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
369cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Could not allocate buffer\n");
370cabdff1aSopenharmony_ci        goto done;
371cabdff1aSopenharmony_ci    }
372cabdff1aSopenharmony_ci
373cabdff1aSopenharmony_ci    /* Override frame->pkt_pts as ff_get_buffer will override its value based
374cabdff1aSopenharmony_ci     * on the last avpacket received which is not in sync with the frame:
375cabdff1aSopenharmony_ci     *   * N avpackets can be pushed before 1 frame is actually returned
376cabdff1aSopenharmony_ci     *   * 0-sized avpackets are pushed to flush remaining frames at EOS */
377cabdff1aSopenharmony_ci    if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
378cabdff1aSopenharmony_ci        frame->pts = av_rescale_q(info->presentationTimeUs,
379cabdff1aSopenharmony_ci                                      AV_TIME_BASE_Q,
380cabdff1aSopenharmony_ci                                      avctx->pkt_timebase);
381cabdff1aSopenharmony_ci    } else {
382cabdff1aSopenharmony_ci        frame->pts = info->presentationTimeUs;
383cabdff1aSopenharmony_ci    }
384cabdff1aSopenharmony_ci    frame->pkt_dts = AV_NOPTS_VALUE;
385cabdff1aSopenharmony_ci
386cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_TRACE,
387cabdff1aSopenharmony_ci            "Frame: width=%d stride=%d height=%d slice-height=%d "
388cabdff1aSopenharmony_ci            "crop-top=%d crop-bottom=%d crop-left=%d crop-right=%d encoder=%s "
389cabdff1aSopenharmony_ci            "destination linesizes=%d,%d,%d\n" ,
390cabdff1aSopenharmony_ci            avctx->width, s->stride, avctx->height, s->slice_height,
391cabdff1aSopenharmony_ci            s->crop_top, s->crop_bottom, s->crop_left, s->crop_right, s->codec_name,
392cabdff1aSopenharmony_ci            frame->linesize[0], frame->linesize[1], frame->linesize[2]);
393cabdff1aSopenharmony_ci
394cabdff1aSopenharmony_ci    switch (s->color_format) {
395cabdff1aSopenharmony_ci    case COLOR_FormatYUV420Planar:
396cabdff1aSopenharmony_ci        ff_mediacodec_sw_buffer_copy_yuv420_planar(avctx, s, data, size, info, frame);
397cabdff1aSopenharmony_ci        break;
398cabdff1aSopenharmony_ci    case COLOR_FormatYUV420SemiPlanar:
399cabdff1aSopenharmony_ci    case COLOR_QCOM_FormatYUV420SemiPlanar:
400cabdff1aSopenharmony_ci    case COLOR_QCOM_FormatYUV420SemiPlanar32m:
401cabdff1aSopenharmony_ci        ff_mediacodec_sw_buffer_copy_yuv420_semi_planar(avctx, s, data, size, info, frame);
402cabdff1aSopenharmony_ci        break;
403cabdff1aSopenharmony_ci    case COLOR_TI_FormatYUV420PackedSemiPlanar:
404cabdff1aSopenharmony_ci    case COLOR_TI_FormatYUV420PackedSemiPlanarInterlaced:
405cabdff1aSopenharmony_ci        ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar(avctx, s, data, size, info, frame);
406cabdff1aSopenharmony_ci        break;
407cabdff1aSopenharmony_ci    case COLOR_QCOM_FormatYUV420PackedSemiPlanar64x32Tile2m8ka:
408cabdff1aSopenharmony_ci        ff_mediacodec_sw_buffer_copy_yuv420_packed_semi_planar_64x32Tile2m8ka(avctx, s, data, size, info, frame);
409cabdff1aSopenharmony_ci        break;
410cabdff1aSopenharmony_ci    default:
411cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Unsupported color format 0x%x (value=%d)\n",
412cabdff1aSopenharmony_ci            s->color_format, s->color_format);
413cabdff1aSopenharmony_ci        ret = AVERROR(EINVAL);
414cabdff1aSopenharmony_ci        goto done;
415cabdff1aSopenharmony_ci    }
416cabdff1aSopenharmony_ci
417cabdff1aSopenharmony_ci    ret = 0;
418cabdff1aSopenharmony_cidone:
419cabdff1aSopenharmony_ci    status = ff_AMediaCodec_releaseOutputBuffer(s->codec, index, 0);
420cabdff1aSopenharmony_ci    if (status < 0) {
421cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to release output buffer\n");
422cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;
423cabdff1aSopenharmony_ci    }
424cabdff1aSopenharmony_ci
425cabdff1aSopenharmony_ci    return ret;
426cabdff1aSopenharmony_ci}
427cabdff1aSopenharmony_ci
428cabdff1aSopenharmony_ci#define AMEDIAFORMAT_GET_INT32(name, key, mandatory) do {                              \
429cabdff1aSopenharmony_ci    int32_t value = 0;                                                                 \
430cabdff1aSopenharmony_ci    if (ff_AMediaFormat_getInt32(s->format, key, &value)) {                            \
431cabdff1aSopenharmony_ci        (name) = value;                                                                \
432cabdff1aSopenharmony_ci    } else if (mandatory) {                                                            \
433cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", key, format); \
434cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;                                                        \
435cabdff1aSopenharmony_ci        goto fail;                                                                     \
436cabdff1aSopenharmony_ci    }                                                                                  \
437cabdff1aSopenharmony_ci} while (0)                                                                            \
438cabdff1aSopenharmony_ci
439cabdff1aSopenharmony_cistatic int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecContext *s)
440cabdff1aSopenharmony_ci{
441cabdff1aSopenharmony_ci    int ret = 0;
442cabdff1aSopenharmony_ci    int width = 0;
443cabdff1aSopenharmony_ci    int height = 0;
444cabdff1aSopenharmony_ci    int color_range = 0;
445cabdff1aSopenharmony_ci    int color_standard = 0;
446cabdff1aSopenharmony_ci    int color_transfer = 0;
447cabdff1aSopenharmony_ci    char *format = NULL;
448cabdff1aSopenharmony_ci
449cabdff1aSopenharmony_ci    if (!s->format) {
450cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Output MediaFormat is not set\n");
451cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
452cabdff1aSopenharmony_ci    }
453cabdff1aSopenharmony_ci
454cabdff1aSopenharmony_ci    format = ff_AMediaFormat_toString(s->format);
455cabdff1aSopenharmony_ci    if (!format) {
456cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
457cabdff1aSopenharmony_ci    }
458cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_DEBUG, "Parsing MediaFormat %s\n", format);
459cabdff1aSopenharmony_ci
460cabdff1aSopenharmony_ci    /* Mandatory fields */
461cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->width,  "width", 1);
462cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->height, "height", 1);
463cabdff1aSopenharmony_ci
464cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->stride, "stride", 0);
465cabdff1aSopenharmony_ci    s->stride = s->stride > 0 ? s->stride : s->width;
466cabdff1aSopenharmony_ci
467cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 0);
468cabdff1aSopenharmony_ci
469cabdff1aSopenharmony_ci    if (strstr(s->codec_name, "OMX.Nvidia.") && s->slice_height == 0) {
470cabdff1aSopenharmony_ci        s->slice_height = FFALIGN(s->height, 16);
471cabdff1aSopenharmony_ci    } else if (strstr(s->codec_name, "OMX.SEC.avc.dec")) {
472cabdff1aSopenharmony_ci        s->slice_height = avctx->height;
473cabdff1aSopenharmony_ci        s->stride = avctx->width;
474cabdff1aSopenharmony_ci    } else if (s->slice_height == 0) {
475cabdff1aSopenharmony_ci        s->slice_height = s->height;
476cabdff1aSopenharmony_ci    }
477cabdff1aSopenharmony_ci
478cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->color_format, "color-format", 1);
479cabdff1aSopenharmony_ci    avctx->pix_fmt = mcdec_map_color_format(avctx, s, s->color_format);
480cabdff1aSopenharmony_ci    if (avctx->pix_fmt == AV_PIX_FMT_NONE) {
481cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Output color format is not supported\n");
482cabdff1aSopenharmony_ci        ret = AVERROR(EINVAL);
483cabdff1aSopenharmony_ci        goto fail;
484cabdff1aSopenharmony_ci    }
485cabdff1aSopenharmony_ci
486cabdff1aSopenharmony_ci    /* Optional fields */
487cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->crop_top,    "crop-top",    0);
488cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->crop_bottom, "crop-bottom", 0);
489cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->crop_left,   "crop-left",   0);
490cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->crop_right,  "crop-right",  0);
491cabdff1aSopenharmony_ci
492cabdff1aSopenharmony_ci    width = s->crop_right + 1 - s->crop_left;
493cabdff1aSopenharmony_ci    height = s->crop_bottom + 1 - s->crop_top;
494cabdff1aSopenharmony_ci
495cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->display_width,  "display-width",  0);
496cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(s->display_height, "display-height", 0);
497cabdff1aSopenharmony_ci
498cabdff1aSopenharmony_ci    if (s->display_width && s->display_height) {
499cabdff1aSopenharmony_ci        AVRational sar = av_div_q(
500cabdff1aSopenharmony_ci            (AVRational){ s->display_width, s->display_height },
501cabdff1aSopenharmony_ci            (AVRational){ width, height });
502cabdff1aSopenharmony_ci        ff_set_sar(avctx, sar);
503cabdff1aSopenharmony_ci    }
504cabdff1aSopenharmony_ci
505cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(color_range, "color-range", 0);
506cabdff1aSopenharmony_ci    if (color_range)
507cabdff1aSopenharmony_ci        avctx->color_range = mcdec_get_color_range(color_range);
508cabdff1aSopenharmony_ci
509cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(color_standard, "color-standard", 0);
510cabdff1aSopenharmony_ci    if (color_standard) {
511cabdff1aSopenharmony_ci        avctx->colorspace = mcdec_get_color_space(color_standard);
512cabdff1aSopenharmony_ci        avctx->color_primaries = mcdec_get_color_pri(color_standard);
513cabdff1aSopenharmony_ci    }
514cabdff1aSopenharmony_ci
515cabdff1aSopenharmony_ci    AMEDIAFORMAT_GET_INT32(color_transfer, "color-transfer", 0);
516cabdff1aSopenharmony_ci    if (color_transfer)
517cabdff1aSopenharmony_ci        avctx->color_trc = mcdec_get_color_trc(color_transfer);
518cabdff1aSopenharmony_ci
519cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_INFO,
520cabdff1aSopenharmony_ci        "Output crop parameters top=%d bottom=%d left=%d right=%d, "
521cabdff1aSopenharmony_ci        "resulting dimensions width=%d height=%d\n",
522cabdff1aSopenharmony_ci        s->crop_top, s->crop_bottom, s->crop_left, s->crop_right,
523cabdff1aSopenharmony_ci        width, height);
524cabdff1aSopenharmony_ci
525cabdff1aSopenharmony_ci    av_freep(&format);
526cabdff1aSopenharmony_ci    return ff_set_dimensions(avctx, width, height);
527cabdff1aSopenharmony_cifail:
528cabdff1aSopenharmony_ci    av_freep(&format);
529cabdff1aSopenharmony_ci    return ret;
530cabdff1aSopenharmony_ci}
531cabdff1aSopenharmony_ci
532cabdff1aSopenharmony_cistatic int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContext *s)
533cabdff1aSopenharmony_ci{
534cabdff1aSopenharmony_ci    FFAMediaCodec *codec = s->codec;
535cabdff1aSopenharmony_ci    int status;
536cabdff1aSopenharmony_ci
537cabdff1aSopenharmony_ci    s->output_buffer_count = 0;
538cabdff1aSopenharmony_ci
539cabdff1aSopenharmony_ci    s->draining = 0;
540cabdff1aSopenharmony_ci    s->flushing = 0;
541cabdff1aSopenharmony_ci    s->eos = 0;
542cabdff1aSopenharmony_ci    atomic_fetch_add(&s->serial, 1);
543cabdff1aSopenharmony_ci    atomic_init(&s->hw_buffer_count, 0);
544cabdff1aSopenharmony_ci    s->current_input_buffer = -1;
545cabdff1aSopenharmony_ci
546cabdff1aSopenharmony_ci    status = ff_AMediaCodec_flush(codec);
547cabdff1aSopenharmony_ci    if (status < 0) {
548cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to flush codec\n");
549cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
550cabdff1aSopenharmony_ci    }
551cabdff1aSopenharmony_ci
552cabdff1aSopenharmony_ci    return 0;
553cabdff1aSopenharmony_ci}
554cabdff1aSopenharmony_ci
555cabdff1aSopenharmony_ciint ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s,
556cabdff1aSopenharmony_ci                           const char *mime, FFAMediaFormat *format)
557cabdff1aSopenharmony_ci{
558cabdff1aSopenharmony_ci    int ret = 0;
559cabdff1aSopenharmony_ci    int status;
560cabdff1aSopenharmony_ci    int profile;
561cabdff1aSopenharmony_ci
562cabdff1aSopenharmony_ci    enum AVPixelFormat pix_fmt;
563cabdff1aSopenharmony_ci    static const enum AVPixelFormat pix_fmts[] = {
564cabdff1aSopenharmony_ci        AV_PIX_FMT_MEDIACODEC,
565cabdff1aSopenharmony_ci        AV_PIX_FMT_NONE,
566cabdff1aSopenharmony_ci    };
567cabdff1aSopenharmony_ci
568cabdff1aSopenharmony_ci    s->avctx = avctx;
569cabdff1aSopenharmony_ci    atomic_init(&s->refcount, 1);
570cabdff1aSopenharmony_ci    atomic_init(&s->hw_buffer_count, 0);
571cabdff1aSopenharmony_ci    atomic_init(&s->serial, 1);
572cabdff1aSopenharmony_ci    s->current_input_buffer = -1;
573cabdff1aSopenharmony_ci
574cabdff1aSopenharmony_ci    pix_fmt = ff_get_format(avctx, pix_fmts);
575cabdff1aSopenharmony_ci    if (pix_fmt == AV_PIX_FMT_MEDIACODEC) {
576cabdff1aSopenharmony_ci        AVMediaCodecContext *user_ctx = avctx->hwaccel_context;
577cabdff1aSopenharmony_ci
578cabdff1aSopenharmony_ci        if (avctx->hw_device_ctx) {
579cabdff1aSopenharmony_ci            AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)(avctx->hw_device_ctx->data);
580cabdff1aSopenharmony_ci            if (device_ctx->type == AV_HWDEVICE_TYPE_MEDIACODEC) {
581cabdff1aSopenharmony_ci                if (device_ctx->hwctx) {
582cabdff1aSopenharmony_ci                    AVMediaCodecDeviceContext *mediacodec_ctx = (AVMediaCodecDeviceContext *)device_ctx->hwctx;
583cabdff1aSopenharmony_ci                    s->surface = ff_mediacodec_surface_ref(mediacodec_ctx->surface, avctx);
584cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_INFO, "Using surface %p\n", s->surface);
585cabdff1aSopenharmony_ci                }
586cabdff1aSopenharmony_ci            }
587cabdff1aSopenharmony_ci        }
588cabdff1aSopenharmony_ci
589cabdff1aSopenharmony_ci        if (!s->surface && user_ctx && user_ctx->surface) {
590cabdff1aSopenharmony_ci            s->surface = ff_mediacodec_surface_ref(user_ctx->surface, avctx);
591cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_INFO, "Using surface %p\n", s->surface);
592cabdff1aSopenharmony_ci        }
593cabdff1aSopenharmony_ci    }
594cabdff1aSopenharmony_ci
595cabdff1aSopenharmony_ci    profile = ff_AMediaCodecProfile_getProfileFromAVCodecContext(avctx);
596cabdff1aSopenharmony_ci    if (profile < 0) {
597cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_WARNING, "Unsupported or unknown profile\n");
598cabdff1aSopenharmony_ci    }
599cabdff1aSopenharmony_ci
600cabdff1aSopenharmony_ci    s->codec_name = ff_AMediaCodecList_getCodecNameByType(mime, profile, 0, avctx);
601cabdff1aSopenharmony_ci    if (!s->codec_name) {
602cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;
603cabdff1aSopenharmony_ci        goto fail;
604cabdff1aSopenharmony_ci    }
605cabdff1aSopenharmony_ci
606cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_DEBUG, "Found decoder %s\n", s->codec_name);
607cabdff1aSopenharmony_ci    s->codec = ff_AMediaCodec_createCodecByName(s->codec_name);
608cabdff1aSopenharmony_ci    if (!s->codec) {
609cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to create media decoder for type %s and name %s\n", mime, s->codec_name);
610cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;
611cabdff1aSopenharmony_ci        goto fail;
612cabdff1aSopenharmony_ci    }
613cabdff1aSopenharmony_ci
614cabdff1aSopenharmony_ci    status = ff_AMediaCodec_configure(s->codec, format, s->surface, NULL, 0);
615cabdff1aSopenharmony_ci    if (status < 0) {
616cabdff1aSopenharmony_ci        char *desc = ff_AMediaFormat_toString(format);
617cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR,
618cabdff1aSopenharmony_ci            "Failed to configure codec %s (status = %d) with format %s\n",
619cabdff1aSopenharmony_ci            s->codec_name, status, desc);
620cabdff1aSopenharmony_ci        av_freep(&desc);
621cabdff1aSopenharmony_ci
622cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;
623cabdff1aSopenharmony_ci        goto fail;
624cabdff1aSopenharmony_ci    }
625cabdff1aSopenharmony_ci
626cabdff1aSopenharmony_ci    status = ff_AMediaCodec_start(s->codec);
627cabdff1aSopenharmony_ci    if (status < 0) {
628cabdff1aSopenharmony_ci        char *desc = ff_AMediaFormat_toString(format);
629cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR,
630cabdff1aSopenharmony_ci            "Failed to start codec %s (status = %d) with format %s\n",
631cabdff1aSopenharmony_ci            s->codec_name, status, desc);
632cabdff1aSopenharmony_ci        av_freep(&desc);
633cabdff1aSopenharmony_ci        ret = AVERROR_EXTERNAL;
634cabdff1aSopenharmony_ci        goto fail;
635cabdff1aSopenharmony_ci    }
636cabdff1aSopenharmony_ci
637cabdff1aSopenharmony_ci    s->format = ff_AMediaCodec_getOutputFormat(s->codec);
638cabdff1aSopenharmony_ci    if (s->format) {
639cabdff1aSopenharmony_ci        if ((ret = mediacodec_dec_parse_format(avctx, s)) < 0) {
640cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR,
641cabdff1aSopenharmony_ci                "Failed to configure context\n");
642cabdff1aSopenharmony_ci            goto fail;
643cabdff1aSopenharmony_ci        }
644cabdff1aSopenharmony_ci    }
645cabdff1aSopenharmony_ci
646cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_DEBUG, "MediaCodec %p started successfully\n", s->codec);
647cabdff1aSopenharmony_ci
648cabdff1aSopenharmony_ci    return 0;
649cabdff1aSopenharmony_ci
650cabdff1aSopenharmony_cifail:
651cabdff1aSopenharmony_ci    av_log(avctx, AV_LOG_ERROR, "MediaCodec %p failed to start\n", s->codec);
652cabdff1aSopenharmony_ci    ff_mediacodec_dec_close(avctx, s);
653cabdff1aSopenharmony_ci    return ret;
654cabdff1aSopenharmony_ci}
655cabdff1aSopenharmony_ci
656cabdff1aSopenharmony_ciint ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s,
657cabdff1aSopenharmony_ci                           AVPacket *pkt, bool wait)
658cabdff1aSopenharmony_ci{
659cabdff1aSopenharmony_ci    int offset = 0;
660cabdff1aSopenharmony_ci    int need_draining = 0;
661cabdff1aSopenharmony_ci    uint8_t *data;
662cabdff1aSopenharmony_ci    size_t size;
663cabdff1aSopenharmony_ci    FFAMediaCodec *codec = s->codec;
664cabdff1aSopenharmony_ci    int status;
665cabdff1aSopenharmony_ci    int64_t input_dequeue_timeout_us = wait ? INPUT_DEQUEUE_TIMEOUT_US : 0;
666cabdff1aSopenharmony_ci    int64_t pts;
667cabdff1aSopenharmony_ci
668cabdff1aSopenharmony_ci    if (s->flushing) {
669cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Decoder is flushing and cannot accept new buffer "
670cabdff1aSopenharmony_ci                                    "until all output buffers have been released\n");
671cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
672cabdff1aSopenharmony_ci    }
673cabdff1aSopenharmony_ci
674cabdff1aSopenharmony_ci    if (pkt->size == 0) {
675cabdff1aSopenharmony_ci        need_draining = 1;
676cabdff1aSopenharmony_ci    }
677cabdff1aSopenharmony_ci
678cabdff1aSopenharmony_ci    if (s->draining && s->eos) {
679cabdff1aSopenharmony_ci        return AVERROR_EOF;
680cabdff1aSopenharmony_ci    }
681cabdff1aSopenharmony_ci
682cabdff1aSopenharmony_ci    while (offset < pkt->size || (need_draining && !s->draining)) {
683cabdff1aSopenharmony_ci        ssize_t index = s->current_input_buffer;
684cabdff1aSopenharmony_ci        if (index < 0) {
685cabdff1aSopenharmony_ci            index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us);
686cabdff1aSopenharmony_ci            if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
687cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n");
688cabdff1aSopenharmony_ci                break;
689cabdff1aSopenharmony_ci            }
690cabdff1aSopenharmony_ci
691cabdff1aSopenharmony_ci            if (index < 0) {
692cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index);
693cabdff1aSopenharmony_ci                return AVERROR_EXTERNAL;
694cabdff1aSopenharmony_ci            }
695cabdff1aSopenharmony_ci        }
696cabdff1aSopenharmony_ci        s->current_input_buffer = -1;
697cabdff1aSopenharmony_ci
698cabdff1aSopenharmony_ci        data = ff_AMediaCodec_getInputBuffer(codec, index, &size);
699cabdff1aSopenharmony_ci        if (!data) {
700cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Failed to get input buffer\n");
701cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
702cabdff1aSopenharmony_ci        }
703cabdff1aSopenharmony_ci
704cabdff1aSopenharmony_ci        pts = pkt->pts;
705cabdff1aSopenharmony_ci        if (pts == AV_NOPTS_VALUE) {
706cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Input packet is missing PTS\n");
707cabdff1aSopenharmony_ci            pts = 0;
708cabdff1aSopenharmony_ci        }
709cabdff1aSopenharmony_ci        if (pts && avctx->pkt_timebase.num && avctx->pkt_timebase.den) {
710cabdff1aSopenharmony_ci            pts = av_rescale_q(pts, avctx->pkt_timebase, AV_TIME_BASE_Q);
711cabdff1aSopenharmony_ci        }
712cabdff1aSopenharmony_ci
713cabdff1aSopenharmony_ci        if (need_draining) {
714cabdff1aSopenharmony_ci            uint32_t flags = ff_AMediaCodec_getBufferFlagEndOfStream(codec);
715cabdff1aSopenharmony_ci
716cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "Sending End Of Stream signal\n");
717cabdff1aSopenharmony_ci
718cabdff1aSopenharmony_ci            status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, 0, pts, flags);
719cabdff1aSopenharmony_ci            if (status < 0) {
720cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR, "Failed to queue input empty buffer (status = %d)\n", status);
721cabdff1aSopenharmony_ci                return AVERROR_EXTERNAL;
722cabdff1aSopenharmony_ci            }
723cabdff1aSopenharmony_ci
724cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_TRACE,
725cabdff1aSopenharmony_ci                   "Queued empty EOS input buffer %zd with flags=%d\n", index, flags);
726cabdff1aSopenharmony_ci
727cabdff1aSopenharmony_ci            s->draining = 1;
728cabdff1aSopenharmony_ci            return 0;
729cabdff1aSopenharmony_ci        }
730cabdff1aSopenharmony_ci
731cabdff1aSopenharmony_ci        size = FFMIN(pkt->size - offset, size);
732cabdff1aSopenharmony_ci        memcpy(data, pkt->data + offset, size);
733cabdff1aSopenharmony_ci        offset += size;
734cabdff1aSopenharmony_ci
735cabdff1aSopenharmony_ci        status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, size, pts, 0);
736cabdff1aSopenharmony_ci        if (status < 0) {
737cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status);
738cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
739cabdff1aSopenharmony_ci        }
740cabdff1aSopenharmony_ci
741cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_TRACE,
742cabdff1aSopenharmony_ci               "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts);
743cabdff1aSopenharmony_ci    }
744cabdff1aSopenharmony_ci
745cabdff1aSopenharmony_ci    if (offset == 0)
746cabdff1aSopenharmony_ci        return AVERROR(EAGAIN);
747cabdff1aSopenharmony_ci    return offset;
748cabdff1aSopenharmony_ci}
749cabdff1aSopenharmony_ci
750cabdff1aSopenharmony_ciint ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s,
751cabdff1aSopenharmony_ci                              AVFrame *frame, bool wait)
752cabdff1aSopenharmony_ci{
753cabdff1aSopenharmony_ci    int ret;
754cabdff1aSopenharmony_ci    uint8_t *data;
755cabdff1aSopenharmony_ci    ssize_t index;
756cabdff1aSopenharmony_ci    size_t size;
757cabdff1aSopenharmony_ci    FFAMediaCodec *codec = s->codec;
758cabdff1aSopenharmony_ci    FFAMediaCodecBufferInfo info = { 0 };
759cabdff1aSopenharmony_ci    int status;
760cabdff1aSopenharmony_ci    int64_t output_dequeue_timeout_us = OUTPUT_DEQUEUE_TIMEOUT_US;
761cabdff1aSopenharmony_ci
762cabdff1aSopenharmony_ci    if (s->draining && s->eos) {
763cabdff1aSopenharmony_ci        return AVERROR_EOF;
764cabdff1aSopenharmony_ci    }
765cabdff1aSopenharmony_ci
766cabdff1aSopenharmony_ci    if (s->draining) {
767cabdff1aSopenharmony_ci        /* If the codec is flushing or need to be flushed, block for a fair
768cabdff1aSopenharmony_ci         * amount of time to ensure we got a frame */
769cabdff1aSopenharmony_ci        output_dequeue_timeout_us = OUTPUT_DEQUEUE_BLOCK_TIMEOUT_US;
770cabdff1aSopenharmony_ci    } else if (s->output_buffer_count == 0 || !wait) {
771cabdff1aSopenharmony_ci        /* If the codec hasn't produced any frames, do not block so we
772cabdff1aSopenharmony_ci         * can push data to it as fast as possible, and get the first
773cabdff1aSopenharmony_ci         * frame */
774cabdff1aSopenharmony_ci        output_dequeue_timeout_us = 0;
775cabdff1aSopenharmony_ci    }
776cabdff1aSopenharmony_ci
777cabdff1aSopenharmony_ci    index = ff_AMediaCodec_dequeueOutputBuffer(codec, &info, output_dequeue_timeout_us);
778cabdff1aSopenharmony_ci    if (index >= 0) {
779cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_TRACE, "Got output buffer %zd"
780cabdff1aSopenharmony_ci                " offset=%" PRIi32 " size=%" PRIi32 " ts=%" PRIi64
781cabdff1aSopenharmony_ci                " flags=%" PRIu32 "\n", index, info.offset, info.size,
782cabdff1aSopenharmony_ci                info.presentationTimeUs, info.flags);
783cabdff1aSopenharmony_ci
784cabdff1aSopenharmony_ci        if (info.flags & ff_AMediaCodec_getBufferFlagEndOfStream(codec)) {
785cabdff1aSopenharmony_ci            s->eos = 1;
786cabdff1aSopenharmony_ci        }
787cabdff1aSopenharmony_ci
788cabdff1aSopenharmony_ci        if (info.size) {
789cabdff1aSopenharmony_ci            if (s->surface) {
790cabdff1aSopenharmony_ci                if ((ret = mediacodec_wrap_hw_buffer(avctx, s, index, &info, frame)) < 0) {
791cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_ERROR, "Failed to wrap MediaCodec buffer\n");
792cabdff1aSopenharmony_ci                    return ret;
793cabdff1aSopenharmony_ci                }
794cabdff1aSopenharmony_ci            } else {
795cabdff1aSopenharmony_ci                data = ff_AMediaCodec_getOutputBuffer(codec, index, &size);
796cabdff1aSopenharmony_ci                if (!data) {
797cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_ERROR, "Failed to get output buffer\n");
798cabdff1aSopenharmony_ci                    return AVERROR_EXTERNAL;
799cabdff1aSopenharmony_ci                }
800cabdff1aSopenharmony_ci
801cabdff1aSopenharmony_ci                if ((ret = mediacodec_wrap_sw_buffer(avctx, s, data, size, index, &info, frame)) < 0) {
802cabdff1aSopenharmony_ci                    av_log(avctx, AV_LOG_ERROR, "Failed to wrap MediaCodec buffer\n");
803cabdff1aSopenharmony_ci                    return ret;
804cabdff1aSopenharmony_ci                }
805cabdff1aSopenharmony_ci            }
806cabdff1aSopenharmony_ci
807cabdff1aSopenharmony_ci            s->output_buffer_count++;
808cabdff1aSopenharmony_ci            return 0;
809cabdff1aSopenharmony_ci        } else {
810cabdff1aSopenharmony_ci            status = ff_AMediaCodec_releaseOutputBuffer(codec, index, 0);
811cabdff1aSopenharmony_ci            if (status < 0) {
812cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR, "Failed to release output buffer\n");
813cabdff1aSopenharmony_ci            }
814cabdff1aSopenharmony_ci        }
815cabdff1aSopenharmony_ci
816cabdff1aSopenharmony_ci    } else if (ff_AMediaCodec_infoOutputFormatChanged(codec, index)) {
817cabdff1aSopenharmony_ci        char *format = NULL;
818cabdff1aSopenharmony_ci
819cabdff1aSopenharmony_ci        if (s->format) {
820cabdff1aSopenharmony_ci            status = ff_AMediaFormat_delete(s->format);
821cabdff1aSopenharmony_ci            if (status < 0) {
822cabdff1aSopenharmony_ci                av_log(avctx, AV_LOG_ERROR, "Failed to delete MediaFormat %p\n", s->format);
823cabdff1aSopenharmony_ci            }
824cabdff1aSopenharmony_ci        }
825cabdff1aSopenharmony_ci
826cabdff1aSopenharmony_ci        s->format = ff_AMediaCodec_getOutputFormat(codec);
827cabdff1aSopenharmony_ci        if (!s->format) {
828cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Failed to get output format\n");
829cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
830cabdff1aSopenharmony_ci        }
831cabdff1aSopenharmony_ci
832cabdff1aSopenharmony_ci        format = ff_AMediaFormat_toString(s->format);
833cabdff1aSopenharmony_ci        if (!format) {
834cabdff1aSopenharmony_ci            return AVERROR_EXTERNAL;
835cabdff1aSopenharmony_ci        }
836cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_INFO, "Output MediaFormat changed to %s\n", format);
837cabdff1aSopenharmony_ci        av_freep(&format);
838cabdff1aSopenharmony_ci
839cabdff1aSopenharmony_ci        if ((ret = mediacodec_dec_parse_format(avctx, s)) < 0) {
840cabdff1aSopenharmony_ci            return ret;
841cabdff1aSopenharmony_ci        }
842cabdff1aSopenharmony_ci
843cabdff1aSopenharmony_ci    } else if (ff_AMediaCodec_infoOutputBuffersChanged(codec, index)) {
844cabdff1aSopenharmony_ci        ff_AMediaCodec_cleanOutputBuffers(codec);
845cabdff1aSopenharmony_ci    } else if (ff_AMediaCodec_infoTryAgainLater(codec, index)) {
846cabdff1aSopenharmony_ci        if (s->draining) {
847cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "Failed to dequeue output buffer within %" PRIi64 "ms "
848cabdff1aSopenharmony_ci                                        "while draining remaining frames, output will probably lack frames\n",
849cabdff1aSopenharmony_ci                                        output_dequeue_timeout_us / 1000);
850cabdff1aSopenharmony_ci        } else {
851cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_TRACE, "No output buffer available, try again later\n");
852cabdff1aSopenharmony_ci        }
853cabdff1aSopenharmony_ci    } else {
854cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to dequeue output buffer (status=%zd)\n", index);
855cabdff1aSopenharmony_ci        return AVERROR_EXTERNAL;
856cabdff1aSopenharmony_ci    }
857cabdff1aSopenharmony_ci
858cabdff1aSopenharmony_ci    return AVERROR(EAGAIN);
859cabdff1aSopenharmony_ci}
860cabdff1aSopenharmony_ci
861cabdff1aSopenharmony_ci/*
862cabdff1aSopenharmony_ci* ff_mediacodec_dec_flush returns 0 if the flush cannot be performed on
863cabdff1aSopenharmony_ci* the codec (because the user retains frames). The codec stays in the
864cabdff1aSopenharmony_ci* flushing state.
865cabdff1aSopenharmony_ci*
866cabdff1aSopenharmony_ci* ff_mediacodec_dec_flush returns 1 if the flush can actually be
867cabdff1aSopenharmony_ci* performed on the codec. The codec leaves the flushing state and can
868cabdff1aSopenharmony_ci* process again packets.
869cabdff1aSopenharmony_ci*
870cabdff1aSopenharmony_ci* ff_mediacodec_dec_flush returns a negative value if an error has
871cabdff1aSopenharmony_ci* occurred.
872cabdff1aSopenharmony_ci*/
873cabdff1aSopenharmony_ciint ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s)
874cabdff1aSopenharmony_ci{
875cabdff1aSopenharmony_ci    if (!s->surface || atomic_load(&s->refcount) == 1) {
876cabdff1aSopenharmony_ci        int ret;
877cabdff1aSopenharmony_ci
878cabdff1aSopenharmony_ci        /* No frames (holding a reference to the codec) are retained by the
879cabdff1aSopenharmony_ci         * user, thus we can flush the codec and returns accordingly */
880cabdff1aSopenharmony_ci        if ((ret = mediacodec_dec_flush_codec(avctx, s)) < 0) {
881cabdff1aSopenharmony_ci            return ret;
882cabdff1aSopenharmony_ci        }
883cabdff1aSopenharmony_ci
884cabdff1aSopenharmony_ci        return 1;
885cabdff1aSopenharmony_ci    }
886cabdff1aSopenharmony_ci
887cabdff1aSopenharmony_ci    s->flushing = 1;
888cabdff1aSopenharmony_ci    return 0;
889cabdff1aSopenharmony_ci}
890cabdff1aSopenharmony_ci
891cabdff1aSopenharmony_ciint ff_mediacodec_dec_close(AVCodecContext *avctx, MediaCodecDecContext *s)
892cabdff1aSopenharmony_ci{
893cabdff1aSopenharmony_ci    ff_mediacodec_dec_unref(s);
894cabdff1aSopenharmony_ci
895cabdff1aSopenharmony_ci    return 0;
896cabdff1aSopenharmony_ci}
897cabdff1aSopenharmony_ci
898cabdff1aSopenharmony_ciint ff_mediacodec_dec_is_flushing(AVCodecContext *avctx, MediaCodecDecContext *s)
899cabdff1aSopenharmony_ci{
900cabdff1aSopenharmony_ci    return s->flushing;
901cabdff1aSopenharmony_ci}
902