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