FFmpeg
Loading...
Searching...
No Matches
libopenh264dec.c
Go to the documentation of this file.
1/*
2 * OpenH264 video decoder
3 * Copyright (C) 2016 Martin Storsjo
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22#include <wels/codec_api.h>
23#include <wels/codec_ver.h>
24
25#include "libavutil/common.h"
26#include "libavutil/fifo.h"
27#include "libavutil/imgutils.h"
30#include "libavutil/opt.h"
31
32#include "avcodec.h"
33#include "codec_internal.h"
34#include "decode.h"
35#include "libopenh264.h"
36
37typedef struct SVCContext {
38 ISVCDecoder *decoder;
40
42{
43 SVCContext *s = avctx->priv_data;
44
45 if (s->decoder) {
46 WelsDestroyDecoder(s->decoder);
47 s->decoder = NULL;
48 }
49
50 return 0;
51}
52
53static av_cold int svc_decode_init(AVCodecContext *avctx);
54
56{
57 svc_decode_close(avctx);
58 svc_decode_init(avctx);
59}
60
62{
63 SVCContext *s = avctx->priv_data;
64 SDecodingParam param = { 0 };
65 int log_level;
66 WelsTraceCallback callback_function;
67
68 if (WelsCreateDecoder(&s->decoder)) {
69 av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n");
70 return AVERROR_UNKNOWN;
71 }
72
73 // Pass all libopenh264 messages to our callback, to allow ourselves to filter them.
74 log_level = WELS_LOG_DETAIL;
75 callback_function = ff_libopenh264_trace_callback;
76 (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_LEVEL, &log_level);
77 (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK, (void *)&callback_function);
78 (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT, (void *)&avctx);
79
80#if !OPENH264_VER_AT_LEAST(1, 6)
81 param.eOutputColorFormat = videoFormatI420;
82#endif
83 param.eEcActiveIdc = ERROR_CON_DISABLE;
84 param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT;
85
86 if ((*s->decoder)->Initialize(s->decoder, &param) != cmResultSuccess) {
87 av_log(avctx, AV_LOG_ERROR, "Initialize failed\n");
88 svc_decode_close(avctx);
89 return AVERROR_UNKNOWN;
90 }
91
93
94 return 0;
95}
96
97static int svc_decode_frame(AVCodecContext *avctx, AVFrame *avframe,
98 int *got_frame, AVPacket *avpkt)
99{
100 SVCContext *s = avctx->priv_data;
101 SBufferInfo info = { 0 };
102 uint8_t *ptrs[4] = { NULL };
103 int ret, linesize[4];
104 DECODING_STATE state;
105#if OPENH264_VER_AT_LEAST(1, 7)
106 int opt;
107#endif
108
109 /* svc_decode_flush() tears the decoder down and re-initializes it. If that
110 * re-init failed (e.g. WelsCreateDecoder/Initialize OOM) s->decoder is left
111 * NULL; the void flush callback cannot report this, so guard here to turn a
112 * NULL dereference into a recoverable error. */
113 if (!s->decoder) {
114 av_log(avctx, AV_LOG_ERROR, "decoder not initialized\n");
115 return AVERROR(EINVAL);
116 }
117
118 if (!avpkt->data) {
119#if OPENH264_VER_AT_LEAST(1, 9)
120 int end_of_stream = 1;
121 (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_END_OF_STREAM, &end_of_stream);
122 state = (*s->decoder)->FlushFrame(s->decoder, ptrs, &info);
123#else
124 return 0;
125#endif
126 } else {
127 info.uiInBsTimeStamp = avpkt->pts;
128#if OPENH264_VER_AT_LEAST(1, 4)
129 // Contrary to the name, DecodeFrameNoDelay actually does buffering
130 // and reordering of frames, and is the recommended decoding entry
131 // point since 1.4. This is essential for successfully decoding
132 // B-frames.
133 state = (*s->decoder)->DecodeFrameNoDelay(s->decoder, avpkt->data, avpkt->size, ptrs, &info);
134#else
135 state = (*s->decoder)->DecodeFrame2(s->decoder, avpkt->data, avpkt->size, ptrs, &info);
136#endif
137 }
138 if (state != dsErrorFree) {
139 av_log(avctx, AV_LOG_ERROR, "DecodeFrame failed\n");
140 return AVERROR_UNKNOWN;
141 }
142 if (info.iBufferStatus != 1) {
143 av_log(avctx, AV_LOG_DEBUG, "No frame produced\n");
144 return avpkt->size;
145 }
146
147 ret = ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight);
148 if (ret < 0)
149 return ret;
150 // The decoder doesn't (currently) support decoding into a user
151 // provided buffer, so do a copy instead.
152 if (ff_get_buffer(avctx, avframe, 0) < 0) {
153 av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n");
154 return AVERROR(ENOMEM);
155 }
156
157 linesize[0] = info.UsrData.sSystemBuffer.iStride[0];
158 linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1];
159 linesize[3] = 0;
160 av_image_copy2(avframe->data, avframe->linesize, ptrs, linesize,
161 avctx->pix_fmt, avctx->width, avctx->height);
162
163 avframe->pts = info.uiOutYuvTimeStamp;
164 avframe->pkt_dts = AV_NOPTS_VALUE;
165#if OPENH264_VER_AT_LEAST(1, 7)
166 (*s->decoder)->GetOption(s->decoder, DECODER_OPTION_PROFILE, &opt);
167 avctx->profile = opt;
168 (*s->decoder)->GetOption(s->decoder, DECODER_OPTION_LEVEL, &opt);
169 avctx->level = opt;
170#endif
171
172 *got_frame = 1;
173 return avpkt->size;
174}
175
177 .p.name = "libopenh264",
178 CODEC_LONG_NAME("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
179 .p.type = AVMEDIA_TYPE_VIDEO,
180 .p.id = AV_CODEC_ID_H264,
181 .priv_data_size = sizeof(SVCContext),
184 .close = svc_decode_close,
185 .flush = svc_decode_flush,
186 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
187 .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS |
189 .bsfs = "h264_mp4toannexb",
190 .p.wrapper_name = "libopenh264",
191};
const FFCodec ff_libopenh264_decoder
Libavcodec external API header.
static int FUNC end_of_stream(CodedBitstreamContext *ctx, RWContext *rw, H264RawNALUnitHeader *current)
#define s(width, name)
Definition cbs_vp9.c:198
#define FF_CODEC_CAP_SETS_PKT_DTS
Decoders marked with FF_CODEC_CAP_SETS_PKT_DTS want to set AVFrame.pkt_dts manually.
#define FF_CODEC_DECODE_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
common internal and external API header
#define NULL
Definition coverity.c:32
int ff_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Get a buffer for a frame.
Definition decode.c:1777
int ff_set_dimensions(AVCodecContext *s, int width, int height)
Definition utils.c:91
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
static struct @346255127015250356166251341105367306144006377143 state
A generic FIFO API.
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition codec.h:79
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
Definition codec.h:49
@ AV_CODEC_ID_H264
Definition codec_id.h:77
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition error.h:73
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static void av_image_copy2(uint8_t *const dst_data[4], const int dst_linesizes[4], uint8_t *const src_data[4], const int src_linesizes[4], enum AVPixelFormat pix_fmt, int width, int height)
Wrapper around av_image_copy() to workaround the limitation that the conversion from uint8_t * const ...
Definition imgutils.h:184
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition avutil.h:247
misc image utilities
#define av_cold
Definition attributes.h:117
void ff_libopenh264_trace_callback(void *ctx, int level, const char *msg)
Definition libopenh264.c:42
static void svc_decode_flush(AVCodecContext *avctx)
static int svc_decode_frame(AVCodecContext *avctx, AVFrame *avframe, int *got_frame, AVPacket *avpkt)
static av_cold int svc_decode_close(AVCodecContext *avctx)
static av_cold int svc_decode_init(AVCodecContext *avctx)
AVOptions.
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
main external API structure.
Definition avcodec.h:443
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition avcodec.h:643
int width
picture width / height.
Definition avcodec.h:604
int level
Encoding level descriptor.
Definition avcodec.h:1646
int profile
profile
Definition avcodec.h:1636
void * priv_data
Definition avcodec.h:470
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition frame.h:574
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
int64_t pkt_dts
DTS copied from the AVPacket that triggered returning this frame.
Definition frame.h:581
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
This structure stores compressed data.
Definition packet.h:580
int size
Definition packet.h:604
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition packet.h:596
uint8_t * data
Definition packet.h:603
ISVCDecoder * decoder
#define av_log(a,...)