1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * OpenH264 video decoder 3cabdff1aSopenharmony_ci * Copyright (C) 2016 Martin Storsjo 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include <wels/codec_api.h> 23cabdff1aSopenharmony_ci#include <wels/codec_ver.h> 24cabdff1aSopenharmony_ci 25cabdff1aSopenharmony_ci#include "libavutil/common.h" 26cabdff1aSopenharmony_ci#include "libavutil/fifo.h" 27cabdff1aSopenharmony_ci#include "libavutil/imgutils.h" 28cabdff1aSopenharmony_ci#include "libavutil/intreadwrite.h" 29cabdff1aSopenharmony_ci#include "libavutil/mathematics.h" 30cabdff1aSopenharmony_ci#include "libavutil/opt.h" 31cabdff1aSopenharmony_ci 32cabdff1aSopenharmony_ci#include "avcodec.h" 33cabdff1aSopenharmony_ci#include "codec_internal.h" 34cabdff1aSopenharmony_ci#include "internal.h" 35cabdff1aSopenharmony_ci#include "libopenh264.h" 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_citypedef struct SVCContext { 38cabdff1aSopenharmony_ci ISVCDecoder *decoder; 39cabdff1aSopenharmony_ci} SVCContext; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_cistatic av_cold int svc_decode_close(AVCodecContext *avctx) 42cabdff1aSopenharmony_ci{ 43cabdff1aSopenharmony_ci SVCContext *s = avctx->priv_data; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci if (s->decoder) 46cabdff1aSopenharmony_ci WelsDestroyDecoder(s->decoder); 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci return 0; 49cabdff1aSopenharmony_ci} 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_cistatic av_cold int svc_decode_init(AVCodecContext *avctx) 52cabdff1aSopenharmony_ci{ 53cabdff1aSopenharmony_ci SVCContext *s = avctx->priv_data; 54cabdff1aSopenharmony_ci SDecodingParam param = { 0 }; 55cabdff1aSopenharmony_ci int err; 56cabdff1aSopenharmony_ci int log_level; 57cabdff1aSopenharmony_ci WelsTraceCallback callback_function; 58cabdff1aSopenharmony_ci 59cabdff1aSopenharmony_ci if ((err = ff_libopenh264_check_version(avctx)) < 0) 60cabdff1aSopenharmony_ci return AVERROR_DECODER_NOT_FOUND; 61cabdff1aSopenharmony_ci 62cabdff1aSopenharmony_ci if (WelsCreateDecoder(&s->decoder)) { 63cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n"); 64cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 65cabdff1aSopenharmony_ci } 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci // Pass all libopenh264 messages to our callback, to allow ourselves to filter them. 68cabdff1aSopenharmony_ci log_level = WELS_LOG_DETAIL; 69cabdff1aSopenharmony_ci callback_function = ff_libopenh264_trace_callback; 70cabdff1aSopenharmony_ci (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_LEVEL, &log_level); 71cabdff1aSopenharmony_ci (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK, (void *)&callback_function); 72cabdff1aSopenharmony_ci (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT, (void *)&avctx); 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci#if !OPENH264_VER_AT_LEAST(1, 6) 75cabdff1aSopenharmony_ci param.eOutputColorFormat = videoFormatI420; 76cabdff1aSopenharmony_ci#endif 77cabdff1aSopenharmony_ci param.eEcActiveIdc = ERROR_CON_DISABLE; 78cabdff1aSopenharmony_ci param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; 79cabdff1aSopenharmony_ci 80cabdff1aSopenharmony_ci if ((*s->decoder)->Initialize(s->decoder, ¶m) != cmResultSuccess) { 81cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); 82cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 83cabdff1aSopenharmony_ci } 84cabdff1aSopenharmony_ci 85cabdff1aSopenharmony_ci avctx->pix_fmt = AV_PIX_FMT_YUV420P; 86cabdff1aSopenharmony_ci 87cabdff1aSopenharmony_ci return 0; 88cabdff1aSopenharmony_ci} 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_cistatic int svc_decode_frame(AVCodecContext *avctx, AVFrame *avframe, 91cabdff1aSopenharmony_ci int *got_frame, AVPacket *avpkt) 92cabdff1aSopenharmony_ci{ 93cabdff1aSopenharmony_ci SVCContext *s = avctx->priv_data; 94cabdff1aSopenharmony_ci SBufferInfo info = { 0 }; 95cabdff1aSopenharmony_ci uint8_t *ptrs[4] = { NULL }; 96cabdff1aSopenharmony_ci int ret, linesize[4]; 97cabdff1aSopenharmony_ci DECODING_STATE state; 98cabdff1aSopenharmony_ci#if OPENH264_VER_AT_LEAST(1, 7) 99cabdff1aSopenharmony_ci int opt; 100cabdff1aSopenharmony_ci#endif 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci if (!avpkt->data) { 103cabdff1aSopenharmony_ci#if OPENH264_VER_AT_LEAST(1, 9) 104cabdff1aSopenharmony_ci int end_of_stream = 1; 105cabdff1aSopenharmony_ci (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_END_OF_STREAM, &end_of_stream); 106cabdff1aSopenharmony_ci state = (*s->decoder)->FlushFrame(s->decoder, ptrs, &info); 107cabdff1aSopenharmony_ci#else 108cabdff1aSopenharmony_ci return 0; 109cabdff1aSopenharmony_ci#endif 110cabdff1aSopenharmony_ci } else { 111cabdff1aSopenharmony_ci info.uiInBsTimeStamp = avpkt->pts; 112cabdff1aSopenharmony_ci#if OPENH264_VER_AT_LEAST(1, 4) 113cabdff1aSopenharmony_ci // Contrary to the name, DecodeFrameNoDelay actually does buffering 114cabdff1aSopenharmony_ci // and reordering of frames, and is the recommended decoding entry 115cabdff1aSopenharmony_ci // point since 1.4. This is essential for successfully decoding 116cabdff1aSopenharmony_ci // B-frames. 117cabdff1aSopenharmony_ci state = (*s->decoder)->DecodeFrameNoDelay(s->decoder, avpkt->data, avpkt->size, ptrs, &info); 118cabdff1aSopenharmony_ci#else 119cabdff1aSopenharmony_ci state = (*s->decoder)->DecodeFrame2(s->decoder, avpkt->data, avpkt->size, ptrs, &info); 120cabdff1aSopenharmony_ci#endif 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci if (state != dsErrorFree) { 123cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "DecodeFrame failed\n"); 124cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 125cabdff1aSopenharmony_ci } 126cabdff1aSopenharmony_ci if (info.iBufferStatus != 1) { 127cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_DEBUG, "No frame produced\n"); 128cabdff1aSopenharmony_ci return avpkt->size; 129cabdff1aSopenharmony_ci } 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci ret = ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight); 132cabdff1aSopenharmony_ci if (ret < 0) 133cabdff1aSopenharmony_ci return ret; 134cabdff1aSopenharmony_ci // The decoder doesn't (currently) support decoding into a user 135cabdff1aSopenharmony_ci // provided buffer, so do a copy instead. 136cabdff1aSopenharmony_ci if (ff_get_buffer(avctx, avframe, 0) < 0) { 137cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n"); 138cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 139cabdff1aSopenharmony_ci } 140cabdff1aSopenharmony_ci 141cabdff1aSopenharmony_ci linesize[0] = info.UsrData.sSystemBuffer.iStride[0]; 142cabdff1aSopenharmony_ci linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1]; 143cabdff1aSopenharmony_ci linesize[3] = 0; 144cabdff1aSopenharmony_ci av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height); 145cabdff1aSopenharmony_ci 146cabdff1aSopenharmony_ci avframe->pts = info.uiOutYuvTimeStamp; 147cabdff1aSopenharmony_ci avframe->pkt_dts = AV_NOPTS_VALUE; 148cabdff1aSopenharmony_ci#if OPENH264_VER_AT_LEAST(1, 7) 149cabdff1aSopenharmony_ci (*s->decoder)->GetOption(s->decoder, DECODER_OPTION_PROFILE, &opt); 150cabdff1aSopenharmony_ci avctx->profile = opt; 151cabdff1aSopenharmony_ci (*s->decoder)->GetOption(s->decoder, DECODER_OPTION_LEVEL, &opt); 152cabdff1aSopenharmony_ci avctx->level = opt; 153cabdff1aSopenharmony_ci#endif 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci *got_frame = 1; 156cabdff1aSopenharmony_ci return avpkt->size; 157cabdff1aSopenharmony_ci} 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_ciconst FFCodec ff_libopenh264_decoder = { 160cabdff1aSopenharmony_ci .p.name = "libopenh264", 161cabdff1aSopenharmony_ci .p.long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), 162cabdff1aSopenharmony_ci .p.type = AVMEDIA_TYPE_VIDEO, 163cabdff1aSopenharmony_ci .p.id = AV_CODEC_ID_H264, 164cabdff1aSopenharmony_ci .priv_data_size = sizeof(SVCContext), 165cabdff1aSopenharmony_ci .init = svc_decode_init, 166cabdff1aSopenharmony_ci FF_CODEC_DECODE_CB(svc_decode_frame), 167cabdff1aSopenharmony_ci .close = svc_decode_close, 168cabdff1aSopenharmony_ci .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, 169cabdff1aSopenharmony_ci .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | 170cabdff1aSopenharmony_ci FF_CODEC_CAP_INIT_CLEANUP, 171cabdff1aSopenharmony_ci .bsfs = "h264_mp4toannexb", 172cabdff1aSopenharmony_ci .p.wrapper_name = "libopenh264", 173cabdff1aSopenharmony_ci}; 174