blob: 26cc8db9d16eea4e84846dba920d9d6aefe108da
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" |
28 | #include "libavutil/intreadwrite.h" |
29 | #include "libavutil/mathematics.h" |
30 | #include "libavutil/opt.h" |
31 | |
32 | #include "avcodec.h" |
33 | #include "internal.h" |
34 | #include "libopenh264.h" |
35 | |
36 | typedef struct SVCContext { |
37 | ISVCDecoder *decoder; |
38 | AVBSFContext *bsf; |
39 | AVFifoBuffer *packet_fifo; |
40 | AVPacket pkt_filtered; |
41 | } SVCContext; |
42 | |
43 | static av_cold int svc_decode_close(AVCodecContext *avctx) |
44 | { |
45 | SVCContext *s = avctx->priv_data; |
46 | AVPacket pkt; |
47 | |
48 | if (s->decoder) |
49 | WelsDestroyDecoder(s->decoder); |
50 | |
51 | while (s->packet_fifo && av_fifo_size(s->packet_fifo) >= sizeof(pkt)) { |
52 | av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL); |
53 | av_packet_unref(&pkt); |
54 | } |
55 | |
56 | av_bsf_free(&s->bsf); |
57 | av_packet_unref(&s->pkt_filtered); |
58 | av_fifo_free(s->packet_fifo); |
59 | |
60 | return 0; |
61 | } |
62 | |
63 | static av_cold int svc_decode_init(AVCodecContext *avctx) |
64 | { |
65 | SVCContext *s = avctx->priv_data; |
66 | SDecodingParam param = { 0 }; |
67 | int err; |
68 | int log_level; |
69 | WelsTraceCallback callback_function; |
70 | |
71 | if ((err = ff_libopenh264_check_version(avctx)) < 0) |
72 | return err; |
73 | |
74 | s->packet_fifo = av_fifo_alloc(sizeof(AVPacket)); |
75 | if (!s->packet_fifo) |
76 | return AVERROR(ENOMEM); |
77 | |
78 | if (WelsCreateDecoder(&s->decoder)) { |
79 | av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n"); |
80 | return AVERROR_UNKNOWN; |
81 | } |
82 | |
83 | // Pass all libopenh264 messages to our callback, to allow ourselves to filter them. |
84 | log_level = WELS_LOG_DETAIL; |
85 | callback_function = ff_libopenh264_trace_callback; |
86 | (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_LEVEL, &log_level); |
87 | (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK, (void *)&callback_function); |
88 | (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT, (void *)&avctx); |
89 | |
90 | #if !OPENH264_VER_AT_LEAST(1, 6) |
91 | param.eOutputColorFormat = videoFormatI420; |
92 | #endif |
93 | param.eEcActiveIdc = ERROR_CON_DISABLE; |
94 | param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; |
95 | |
96 | if ((*s->decoder)->Initialize(s->decoder, ¶m) != cmResultSuccess) { |
97 | av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); |
98 | return AVERROR_UNKNOWN; |
99 | } |
100 | |
101 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; |
102 | |
103 | return 0; |
104 | } |
105 | |
106 | static int init_bsf(AVCodecContext *avctx) |
107 | { |
108 | SVCContext *s = avctx->priv_data; |
109 | const AVBitStreamFilter *filter; |
110 | int ret; |
111 | |
112 | if (s->bsf) |
113 | return 0; |
114 | |
115 | // If the input stream already is annex b, this BSF only passes the |
116 | // packets through unchanged. |
117 | filter = av_bsf_get_by_name("h264_mp4toannexb"); |
118 | if (!filter) |
119 | return AVERROR_BUG; |
120 | |
121 | ret = av_bsf_alloc(filter, &s->bsf); |
122 | if (ret < 0) |
123 | return ret; |
124 | |
125 | ret = avcodec_parameters_from_context(s->bsf->par_in, avctx); |
126 | if (ret < 0) |
127 | return ret; |
128 | |
129 | s->bsf->time_base_in = avctx->time_base; |
130 | |
131 | ret = av_bsf_init(s->bsf); |
132 | if (ret < 0) |
133 | return ret; |
134 | |
135 | return ret; |
136 | } |
137 | |
138 | static int svc_decode_frame(AVCodecContext *avctx, void *data, |
139 | int *got_frame, AVPacket *avpkt) |
140 | { |
141 | SVCContext *s = avctx->priv_data; |
142 | SBufferInfo info = { 0 }; |
143 | uint8_t* ptrs[3]; |
144 | int linesize[3]; |
145 | AVFrame *avframe = data; |
146 | int ret; |
147 | DECODING_STATE state; |
148 | |
149 | if ((ret = init_bsf(avctx)) < 0) |
150 | return ret; |
151 | |
152 | if (avpkt->size) { |
153 | AVPacket input_ref = { 0 }; |
154 | if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { |
155 | ret = av_fifo_realloc2(s->packet_fifo, |
156 | av_fifo_size(s->packet_fifo) + sizeof(input_ref)); |
157 | if (ret < 0) |
158 | return ret; |
159 | } |
160 | |
161 | ret = av_packet_ref(&input_ref, avpkt); |
162 | if (ret < 0) |
163 | return ret; |
164 | av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); |
165 | } |
166 | |
167 | while (!*got_frame) { |
168 | /* prepare the input data -- convert to Annex B if needed */ |
169 | if (s->pkt_filtered.size <= 0) { |
170 | AVPacket input_ref; |
171 | |
172 | /* no more data */ |
173 | if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) |
174 | return avpkt->size ? avpkt->size : 0; |
175 | |
176 | av_packet_unref(&s->pkt_filtered); |
177 | |
178 | av_fifo_generic_read(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); |
179 | ret = av_bsf_send_packet(s->bsf, &input_ref); |
180 | if (ret < 0) { |
181 | av_packet_unref(&input_ref); |
182 | return ret; |
183 | } |
184 | |
185 | ret = av_bsf_receive_packet(s->bsf, &s->pkt_filtered); |
186 | if (ret < 0) |
187 | av_packet_move_ref(&s->pkt_filtered, &input_ref); |
188 | else |
189 | av_packet_unref(&input_ref); |
190 | } |
191 | |
192 | state = (*s->decoder)->DecodeFrame2(s->decoder, s->pkt_filtered.data, s->pkt_filtered.size, ptrs, &info); |
193 | s->pkt_filtered.size = 0; |
194 | if (state != dsErrorFree) { |
195 | av_log(avctx, AV_LOG_ERROR, "DecodeFrame2 failed\n"); |
196 | return AVERROR_UNKNOWN; |
197 | } |
198 | if (info.iBufferStatus != 1) { |
199 | av_log(avctx, AV_LOG_DEBUG, "No frame produced\n"); |
200 | continue; |
201 | } |
202 | |
203 | ret = ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight); |
204 | if (ret < 0) |
205 | return ret; |
206 | // The decoder doesn't (currently) support decoding into a user |
207 | // provided buffer, so do a copy instead. |
208 | if (ff_get_buffer(avctx, avframe, 0) < 0) { |
209 | av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n"); |
210 | return AVERROR(ENOMEM); |
211 | } |
212 | |
213 | linesize[0] = info.UsrData.sSystemBuffer.iStride[0]; |
214 | linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1]; |
215 | av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height); |
216 | |
217 | avframe->pts = s->pkt_filtered.pts; |
218 | avframe->pkt_dts = s->pkt_filtered.dts; |
219 | #if FF_API_PKT_PTS |
220 | FF_DISABLE_DEPRECATION_WARNINGS |
221 | avframe->pkt_pts = s->pkt_filtered.pts; |
222 | FF_ENABLE_DEPRECATION_WARNINGS |
223 | #endif |
224 | |
225 | *got_frame = 1; |
226 | } |
227 | return avpkt->size; |
228 | } |
229 | |
230 | AVCodec ff_libopenh264_decoder = { |
231 | .name = "libopenh264", |
232 | .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), |
233 | .type = AVMEDIA_TYPE_VIDEO, |
234 | .id = AV_CODEC_ID_H264, |
235 | .priv_data_size = sizeof(SVCContext), |
236 | .init = svc_decode_init, |
237 | .decode = svc_decode_frame, |
238 | .close = svc_decode_close, |
239 | // The decoder doesn't currently support B-frames, and the decoder's API |
240 | // doesn't support reordering/delay, but the BSF could incur delay. |
241 | .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, |
242 | .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | |
243 | FF_CODEC_CAP_INIT_CLEANUP, |
244 | }; |
245 |