While it is less featureful (and slower) than the built-in H264 decoder, one could potentially want to use it to take advantage of the cisco patent license offer.
Unified · Split
| @@ -60,6 +60,7 @@ version <next>: · 59 unmodified lines | |||
| 60 | - MagicYUV decoder | 60 | - MagicYUV decoder |
| 61 | - Duck TrueMotion 2.0 Real Time decoder | 61 | - Duck TrueMotion 2.0 Real Time decoder |
| 62 | - Intel QSV video scaling filter | 62 | - Intel QSV video scaling filter |
| 63 | - OpenH264 decoder wrapper | ||
| 63 | 64 | ||
| 64 | 65 | ||
| 65 | version 11: | 66 | version 11: |
| @@ -2235,6 +2235,8 @@ libopencore_amrnb_decoder_deps="libopencore_amrnb" · 2234 unmodified lines | |||
| 2235 | libopencore_amrnb_encoder_deps="libopencore_amrnb" | 2235 | libopencore_amrnb_encoder_deps="libopencore_amrnb" |
| 2236 | libopencore_amrnb_encoder_select="audio_frame_queue" | 2236 | libopencore_amrnb_encoder_select="audio_frame_queue" |
| 2237 | libopencore_amrwb_decoder_deps="libopencore_amrwb" | 2237 | libopencore_amrwb_decoder_deps="libopencore_amrwb" |
| 2238 | libopenh264_decoder_deps="libopenh264" | ||
| 2239 | libopenh264_decoder_select="h264_mp4toannexb_bsf" | ||
| 2238 | libopenh264_encoder_deps="libopenh264" | 2240 | libopenh264_encoder_deps="libopenh264" |
| 2239 | libopenjpeg_decoder_deps="libopenjpeg" | 2241 | libopenjpeg_decoder_deps="libopenjpeg" |
| 2240 | libopenjpeg_encoder_deps="libopenjpeg" | 2242 | libopenjpeg_encoder_deps="libopenjpeg" |
| @@ -97,12 +97,19 @@ enable it. · 96 unmodified lines | |||
| 97 | 97 | ||
| 98 | @section OpenH264 | 98 | @section OpenH264 |
| 99 | 99 | ||
| 100 | Libav can make use of the OpenH264 library for H.264 encoding. | 100 | Libav can make use of the OpenH264 library for H.264 encoding and decoding. |
| 101 | 101 | ||
| 102 | Go to @url{http://www.openh264.org/} and follow the instructions for | 102 | Go to @url{http://www.openh264.org/} and follow the instructions for |
| 103 | installing the library. Then pass @code{--enable-libopenh264} to configure to | 103 | installing the library. Then pass @code{--enable-libopenh264} to configure to |
| 104 | enable it. | 104 | enable it. |
| 105 | 105 | ||
| 106 | For decoding, this library is much more limited than the built-in decoder | ||
| 107 | in libavcodec; currently, this library lacks support for decoding B-frames | ||
| 108 | and some other main/high profile features. (It currently only supports | ||
| 109 | constrained baseline profile and CABAC.) Using it is mostly useful for | ||
| 110 | testing and for taking advantage of Cisco's patent portfolio license | ||
| 111 | (@url{http://www.openh264.org/BINARY_LICENSE.txt}). | ||
| 112 | |||
| 106 | @section x264 | 113 | @section x264 |
| 107 | 114 | ||
| 108 | Libav can make use of the x264 library for H.264 encoding. | 115 | Libav can make use of the x264 library for H.264 encoding. |
| @@ -678,7 +678,8 @@ OBJS-$(CONFIG_LIBMP3LAME_ENCODER) += libmp3lame.o mpegaudiodecheader.o · 677 unmodified lines | |||
| 678 | OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o | 678 | OBJS-$(CONFIG_LIBOPENCORE_AMRNB_DECODER) += libopencore-amr.o |
| 679 | OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o | 679 | OBJS-$(CONFIG_LIBOPENCORE_AMRNB_ENCODER) += libopencore-amr.o |
| 680 | OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o | 680 | OBJS-$(CONFIG_LIBOPENCORE_AMRWB_DECODER) += libopencore-amr.o |
| 681 | OBJS-$(CONFIG_LIBOPENH264_ENCODER) += libopenh264enc.o | 681 | OBJS-$(CONFIG_LIBOPENH264_DECODER) += libopenh264dec.o libopenh264.o |
| 682 | OBJS-$(CONFIG_LIBOPENH264_ENCODER) += libopenh264enc.o libopenh264.o | ||
| 682 | OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o | 683 | OBJS-$(CONFIG_LIBOPENJPEG_DECODER) += libopenjpegdec.o |
| 683 | OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o | 684 | OBJS-$(CONFIG_LIBOPENJPEG_ENCODER) += libopenjpegenc.o |
| 684 | OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \ | 685 | OBJS-$(CONFIG_LIBOPUS_DECODER) += libopusdec.o libopus.o \ |
| @@ -488,7 +488,7 @@ void avcodec_register_all(void) · 487 unmodified lines | |||
| 488 | 488 | ||
| 489 | /* external libraries, that shouldn't be used by default if one of the | 489 | /* external libraries, that shouldn't be used by default if one of the |
| 490 | * above is available */ | 490 | * above is available */ |
| 491 | REGISTER_ENCODER(LIBOPENH264, libopenh264); | 491 | REGISTER_ENCDEC (LIBOPENH264, libopenh264); |
| 492 | REGISTER_ENCODER(H264_NVENC, h264_nvenc); | 492 | REGISTER_ENCODER(H264_NVENC, h264_nvenc); |
| 493 | REGISTER_ENCODER(H264_OMX, h264_omx); | 493 | REGISTER_ENCODER(H264_OMX, h264_omx); |
| 494 | REGISTER_ENCODER(H264_QSV, h264_qsv); | 494 | REGISTER_ENCODER(H264_QSV, h264_qsv); |
| @@ -0,0 +1,62 @@ | |||
| 1 | /* | ||
| 2 | * OpenH264 shared utils | ||
| 3 | * Copyright (C) 2014 Martin Storsjo | ||
| 4 | * | ||
| 5 | * This file is part of Libav. | ||
| 6 | * | ||
| 7 | * Libav 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 | * Libav 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 Libav; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <string.h> | ||
| 23 | #include <wels/codec_api.h> | ||
| 24 | #include <wels/codec_ver.h> | ||
| 25 | |||
| 26 | #include "libavutil/log.h" | ||
| 27 | |||
| 28 | #include "libopenh264.h" | ||
| 29 | |||
| 30 | // Convert libopenh264 log level to equivalent libav log level. | ||
| 31 | static int libopenh264_to_libav_log_level(int libopenh264_log_level) | ||
| 32 | { | ||
| 33 | if (libopenh264_log_level >= WELS_LOG_DETAIL) return AV_LOG_TRACE; | ||
| 34 | else if (libopenh264_log_level >= WELS_LOG_DEBUG) return AV_LOG_DEBUG; | ||
| 35 | else if (libopenh264_log_level >= WELS_LOG_INFO) return AV_LOG_VERBOSE; | ||
| 36 | else if (libopenh264_log_level >= WELS_LOG_WARNING) return AV_LOG_WARNING; | ||
| 37 | else if (libopenh264_log_level >= WELS_LOG_ERROR) return AV_LOG_ERROR; | ||
| 38 | else return AV_LOG_QUIET; | ||
| 39 | } | ||
| 40 | |||
| 41 | void ff_libopenh264_trace_callback(void *ctx, int level, const char *msg) | ||
| 42 | { | ||
| 43 | // The message will be logged only if the requested EQUIVALENT libav log level is | ||
| 44 | // less than or equal to the current libav log level. | ||
| 45 | int equiv_libav_log_level = libopenh264_to_libav_log_level(level); | ||
| 46 | av_log(ctx, equiv_libav_log_level, "%s\n", msg); | ||
| 47 | } | ||
| 48 | |||
| 49 | int ff_libopenh264_check_version(void *logctx) | ||
| 50 | { | ||
| 51 | // Mingw GCC < 4.7 on x86_32 uses an incorrect/buggy ABI for the WelsGetCodecVersion | ||
| 52 | // function (for functions returning larger structs), thus skip the check in those | ||
| 53 | // configurations. | ||
| 54 | #if !defined(_WIN32) || !defined(__GNUC__) || !ARCH_X86_32 || AV_GCC_VERSION_AT_LEAST(4, 7) | ||
| 55 | OpenH264Version libver = WelsGetCodecVersion(); | ||
| 56 | if (memcmp(&libver, &g_stCodecVersion, sizeof(libver))) { | ||
| 57 | av_log(logctx, AV_LOG_ERROR, "Incorrect library version loaded\n"); | ||
| 58 | return AVERROR(EINVAL); | ||
| 59 | } | ||
| 60 | #endif | ||
| 61 | return 0; | ||
| 62 | } | ||
| @@ -0,0 +1,39 @@ | |||
| 1 | /* | ||
| 2 | * OpenH264 shared utils | ||
| 3 | * Copyright (C) 2014 Martin Storsjo | ||
| 4 | * | ||
| 5 | * This file is part of Libav. | ||
| 6 | * | ||
| 7 | * Libav 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 | * Libav 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 Libav; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 20 | */ | ||
| 21 | |||
| 22 | #ifndef AVCODEC_LIBOPENH264_H | ||
| 23 | #define AVCODEC_LIBOPENH264_H | ||
| 24 | |||
| 25 | #define OPENH264_VER_AT_LEAST(maj, min) \ | ||
| 26 | ((OPENH264_MAJOR > (maj)) || \ | ||
| 27 | (OPENH264_MAJOR == (maj) && OPENH264_MINOR >= (min))) | ||
| 28 | |||
| 29 | // This function will be provided to the libopenh264 library. The function will be called | ||
| 30 | // when libopenh264 wants to log a message (error, warning, info, etc.). The signature for | ||
| 31 | // this function (defined in .../codec/api/svc/codec_api.h) is: | ||
| 32 | // | ||
| 33 | // typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string); | ||
| 34 | |||
| 35 | void ff_libopenh264_trace_callback(void *ctx, int level, const char *msg); | ||
| 36 | |||
| 37 | int ff_libopenh264_check_version(void *logctx); | ||
| 38 | |||
| 39 | #endif /* AVCODEC_LIBOPENH264_H */ | ||
| @@ -0,0 +1,245 @@ | |||
| 1 | /* | ||
| 2 | * OpenH264 video decoder | ||
| 3 | * Copyright (C) 2016 Martin Storsjo | ||
| 4 | * | ||
| 5 | * This file is part of Libav. | ||
| 6 | * | ||
| 7 | * Libav 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 | * Libav 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 Libav; 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 (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 | err = AVERROR(ENOMEM); | ||
| 77 | goto fail; | ||
| 78 | } | ||
| 79 | |||
| 80 | if (WelsCreateDecoder(&s->decoder)) { | ||
| 81 | av_log(avctx, AV_LOG_ERROR, "Unable to create decoder\n"); | ||
| 82 | err = AVERROR_UNKNOWN; | ||
| 83 | goto fail; | ||
| 84 | } | ||
| 85 | |||
| 86 | // Pass all libopenh264 messages to our callback, to allow ourselves to filter them. | ||
| 87 | log_level = WELS_LOG_DETAIL; | ||
| 88 | callback_function = ff_libopenh264_trace_callback; | ||
| 89 | (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_LEVEL, &log_level); | ||
| 90 | (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK, (void *)&callback_function); | ||
| 91 | (*s->decoder)->SetOption(s->decoder, DECODER_OPTION_TRACE_CALLBACK_CONTEXT, (void *)&avctx); | ||
| 92 | |||
| 93 | param.eOutputColorFormat = videoFormatI420; | ||
| 94 | param.eEcActiveIdc = ERROR_CON_DISABLE; | ||
| 95 | param.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_DEFAULT; | ||
| 96 | |||
| 97 | if ((*s->decoder)->Initialize(s->decoder, ¶m) != cmResultSuccess) { | ||
| 98 | av_log(avctx, AV_LOG_ERROR, "Initialize failed\n"); | ||
| 99 | err = AVERROR_UNKNOWN; | ||
| 100 | goto fail; | ||
| 101 | } | ||
| 102 | |||
| 103 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | ||
| 104 | |||
| 105 | fail: | ||
| 106 | return err; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int init_bsf(AVCodecContext *avctx) | ||
| 110 | { | ||
| 111 | SVCContext *s = avctx->priv_data; | ||
| 112 | const AVBitStreamFilter *filter; | ||
| 113 | int ret; | ||
| 114 | |||
| 115 | if (s->bsf) | ||
| 116 | return 0; | ||
| 117 | |||
| 118 | // If the input stream already is annex b, this BSF only passes the | ||
| 119 | // packets through unchanged. | ||
| 120 | filter = av_bsf_get_by_name("h264_mp4toannexb"); | ||
| 121 | if (!filter) | ||
| 122 | return AVERROR_BUG; | ||
| 123 | |||
| 124 | ret = av_bsf_alloc(filter, &s->bsf); | ||
| 125 | if (ret < 0) | ||
| 126 | return ret; | ||
| 127 | |||
| 128 | ret = avcodec_parameters_from_context(s->bsf->par_in, avctx); | ||
| 129 | if (ret < 0) | ||
| 130 | return ret; | ||
| 131 | |||
| 132 | s->bsf->time_base_in = avctx->time_base; | ||
| 133 | |||
| 134 | ret = av_bsf_init(s->bsf); | ||
| 135 | if (ret < 0) | ||
| 136 | return ret; | ||
| 137 | |||
| 138 | return ret; | ||
| 139 | } | ||
| 140 | |||
| 141 | static int svc_decode_frame(AVCodecContext *avctx, void *data, | ||
| 142 | int *got_frame, AVPacket *avpkt) | ||
| 143 | { | ||
| 144 | SVCContext *s = avctx->priv_data; | ||
| 145 | SBufferInfo info = { 0 }; | ||
| 146 | uint8_t* ptrs[3]; | ||
| 147 | int linesize[3]; | ||
| 148 | AVFrame *avframe = data; | ||
| 149 | int ret; | ||
| 150 | DECODING_STATE state; | ||
| 151 | |||
| 152 | if ((ret = init_bsf(avctx)) < 0) | ||
| 153 | return ret; | ||
| 154 | |||
| 155 | if (avpkt->size) { | ||
| 156 | AVPacket input_ref = { 0 }; | ||
| 157 | if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) { | ||
| 158 | ret = av_fifo_realloc2(s->packet_fifo, | ||
| 159 | av_fifo_size(s->packet_fifo) + sizeof(input_ref)); | ||
| 160 | if (ret < 0) | ||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | |||
| 164 | ret = av_packet_ref(&input_ref, avpkt); | ||
| 165 | if (ret < 0) | ||
| 166 | return ret; | ||
| 167 | av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); | ||
| 168 | } | ||
| 169 | |||
| 170 | while (!*got_frame) { | ||
| 171 | /* prepare the input data -- convert to Annex B if needed */ | ||
| 172 | if (s->pkt_filtered.size <= 0) { | ||
| 173 | AVPacket input_ref; | ||
| 174 | |||
| 175 | /* no more data */ | ||
| 176 | if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket)) | ||
| 177 | return avpkt->size ? avpkt->size : 0; | ||
| 178 | |||
| 179 | av_packet_unref(&s->pkt_filtered); | ||
| 180 | |||
| 181 | av_fifo_generic_read(s->packet_fifo, &input_ref, sizeof(input_ref), NULL); | ||
| 182 | ret = av_bsf_send_packet(s->bsf, &input_ref); | ||
| 183 | if (ret < 0) { | ||
| 184 | av_packet_unref(&input_ref); | ||
| 185 | return ret; | ||
| 186 | } | ||
| 187 | |||
| 188 | ret = av_bsf_receive_packet(s->bsf, &s->pkt_filtered); | ||
| 189 | if (ret < 0) | ||
| 190 | av_packet_move_ref(&s->pkt_filtered, &input_ref); | ||
| 191 | else | ||
| 192 | av_packet_unref(&input_ref); | ||
| 193 | } | ||
| 194 | |||
| 195 | state = (*s->decoder)->DecodeFrame2(s->decoder, s->pkt_filtered.data, s->pkt_filtered.size, ptrs, &info); | ||
| 196 | s->pkt_filtered.size = 0; | ||
| 197 | if (state != dsErrorFree) { | ||
| 198 | av_log(avctx, AV_LOG_ERROR, "DecodeFrame2 failed\n"); | ||
| 199 | return AVERROR_UNKNOWN; | ||
| 200 | } | ||
| 201 | if (info.iBufferStatus != 1) { | ||
| 202 | av_log(avctx, AV_LOG_DEBUG, "No frame produced\n"); | ||
| 203 | continue; | ||
| 204 | } | ||
| 205 | |||
| 206 | ff_set_dimensions(avctx, info.UsrData.sSystemBuffer.iWidth, info.UsrData.sSystemBuffer.iHeight); | ||
| 207 | // The decoder doesn't (currently) support decoding into a user | ||
| 208 | // provided buffer, so do a copy instead. | ||
| 209 | if (ff_get_buffer(avctx, avframe, 0) < 0) { | ||
| 210 | av_log(avctx, AV_LOG_ERROR, "Unable to allocate buffer\n"); | ||
| 211 | return AVERROR(ENOMEM); | ||
| 212 | } | ||
| 213 | |||
| 214 | linesize[0] = info.UsrData.sSystemBuffer.iStride[0]; | ||
| 215 | linesize[1] = linesize[2] = info.UsrData.sSystemBuffer.iStride[1]; | ||
| 216 | av_image_copy(avframe->data, avframe->linesize, (const uint8_t **) ptrs, linesize, avctx->pix_fmt, avctx->width, avctx->height); | ||
| 217 | |||
| 218 | avframe->pts = s->pkt_filtered.pts; | ||
| 219 | avframe->pkt_dts = s->pkt_filtered.dts; | ||
| 220 | #if FF_API_PKT_PTS | ||
| 221 | FF_DISABLE_DEPRECATION_WARNINGS | ||
| 222 | avframe->pkt_pts = s->pkt_filtered.pts; | ||
| 223 | FF_ENABLE_DEPRECATION_WARNINGS | ||
| 224 | #endif | ||
| 225 | |||
| 226 | *got_frame = 1; | ||
| 227 | } | ||
| 228 | return avpkt->size; | ||
| 229 | } | ||
| 230 | |||
| 231 | AVCodec ff_libopenh264_decoder = { | ||
| 232 | .name = "libopenh264", | ||
| 233 | .long_name = NULL_IF_CONFIG_SMALL("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), | ||
| 234 | .type = AVMEDIA_TYPE_VIDEO, | ||
| 235 | .id = AV_CODEC_ID_H264, | ||
| 236 | .priv_data_size = sizeof(SVCContext), | ||
| 237 | .init = svc_decode_init, | ||
| 238 | .decode = svc_decode_frame, | ||
| 239 | .close = svc_decode_close, | ||
| 240 | // The decoder doesn't currently support B-frames, and the decoder's API | ||
| 241 | // doesn't support reordering/delay, but the BSF could incur delay. | ||
| 242 | .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1, | ||
| 243 | .caps_internal = FF_CODEC_CAP_SETS_PKT_DTS | FF_CODEC_CAP_INIT_THREADSAFE | | ||
| 244 | FF_CODEC_CAP_INIT_CLEANUP, | ||
| 245 | }; | ||
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | 31 | ||
| 32 | #include "avcodec.h" | 32 | #include "avcodec.h" |
| 33 | #include "internal.h" | 33 | #include "internal.h" |
| 34 | #include "libopenh264.h" | ||
| 34 | 35 | ||
| 35 | typedef struct SVCContext { | 36 | typedef struct SVCContext { |
| 36 | const AVClass *av_class; | 37 | const AVClass *av_class; |
| @@ -44,10 +45,6 @@ typedef struct SVCContext { · 7 unmodified lines | |||
| 44 | int cabac; | 45 | int cabac; |
| 45 | } SVCContext; | 46 | } SVCContext; |
| 46 | 47 | ||
| 47 | #define OPENH264_VER_AT_LEAST(maj, min) \ | ||
| 48 | ((OPENH264_MAJOR > (maj)) || \ | ||
| 49 | (OPENH264_MAJOR == (maj) && OPENH264_MINOR >= (min))) | ||
| 50 | |||
| 51 | #define OFFSET(x) offsetof(SVCContext, x) | 48 | #define OFFSET(x) offsetof(SVCContext, x) |
| 52 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM | 49 | #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
| 53 | static const AVOption options[] = { | 50 | static const AVOption options[] = { |
| @@ -68,31 +65,6 @@ static const AVClass class = { · 14 unmodified lines | |||
| 68 | "libopenh264enc", av_default_item_name, options, LIBAVUTIL_VERSION_INT | 65 | "libopenh264enc", av_default_item_name, options, LIBAVUTIL_VERSION_INT |
| 69 | }; | 66 | }; |
| 70 | 67 | ||
| 71 | // Convert libopenh264 log level to equivalent libav log level. | ||
| 72 | static int libopenh264_to_libav_log_level(int libopenh264_log_level) | ||
| 73 | { | ||
| 74 | if (libopenh264_log_level >= WELS_LOG_DETAIL) return AV_LOG_TRACE; | ||
| 75 | else if (libopenh264_log_level >= WELS_LOG_DEBUG) return AV_LOG_DEBUG; | ||
| 76 | else if (libopenh264_log_level >= WELS_LOG_INFO) return AV_LOG_VERBOSE; | ||
| 77 | else if (libopenh264_log_level >= WELS_LOG_WARNING) return AV_LOG_WARNING; | ||
| 78 | else if (libopenh264_log_level >= WELS_LOG_ERROR) return AV_LOG_ERROR; | ||
| 79 | else return AV_LOG_QUIET; | ||
| 80 | } | ||
| 81 | |||
| 82 | // This function will be provided to the libopenh264 library. The function will be called | ||
| 83 | // when libopenh264 wants to log a message (error, warning, info, etc.). The signature for | ||
| 84 | // this function (defined in .../codec/api/svc/codec_api.h) is: | ||
| 85 | // | ||
| 86 | // typedef void (*WelsTraceCallback) (void* ctx, int level, const char* string); | ||
| 87 | |||
| 88 | static void libopenh264_trace_callback(void *ctx, int level, const char *msg) | ||
| 89 | { | ||
| 90 | // The message will be logged only if the requested EQUIVALENT libav log level is | ||
| 91 | // less than or equal to the current libav log level. | ||
| 92 | int equiv_libav_log_level = libopenh264_to_libav_log_level(level); | ||
| 93 | av_log(ctx, equiv_libav_log_level, "%s\n", msg); | ||
| 94 | } | ||
| 95 | |||
| 96 | static av_cold int svc_encode_close(AVCodecContext *avctx) | 68 | static av_cold int svc_encode_close(AVCodecContext *avctx) |
| 97 | { | 69 | { |
| 98 | SVCContext *s = avctx->priv_data; | 70 | SVCContext *s = avctx->priv_data; |
| @@ -108,21 +80,15 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) · 9 unmodified lines | |||
| 108 | { | 80 | { |
| 109 | SVCContext *s = avctx->priv_data; | 81 | SVCContext *s = avctx->priv_data; |
| 110 | SEncParamExt param = { 0 }; | 82 | SEncParamExt param = { 0 }; |
| 111 | int err = AVERROR_UNKNOWN; | 83 | int err; |
| 112 | int log_level; | 84 | int log_level; |
| 113 | WelsTraceCallback callback_function; | 85 | WelsTraceCallback callback_function; |
| 114 | AVCPBProperties *props; | 86 | AVCPBProperties *props; |
| 115 | 87 | ||
| 116 | // Mingw GCC < 4.7 on x86_32 uses an incorrect/buggy ABI for the WelsGetCodecVersion | 88 | if ((err = ff_libopenh264_check_version(avctx)) < 0) |
| 117 | // function (for functions returning larger structs), thus skip the check in those | 89 | return err; |
| 118 | // configurations. | 90 | // Use a default error for multiple error paths below |
| 119 | #if !defined(_WIN32) || !defined(__GNUC__) || !ARCH_X86_32 || AV_GCC_VERSION_AT_LEAST(4, 7) | 91 | err = AVERROR_UNKNOWN; |
| 120 | OpenH264Version libver = WelsGetCodecVersion(); | ||
| 121 | if (memcmp(&libver, &g_stCodecVersion, sizeof(libver))) { | ||
| 122 | av_log(avctx, AV_LOG_ERROR, "Incorrect library version loaded\n"); | ||
| 123 | return AVERROR(EINVAL); | ||
| 124 | } | ||
| 125 | #endif | ||
| 126 | 92 | ||
| 127 | if (WelsCreateSVCEncoder(&s->encoder)) { | 93 | if (WelsCreateSVCEncoder(&s->encoder)) { |
| 128 | av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n"); | 94 | av_log(avctx, AV_LOG_ERROR, "Unable to create encoder\n"); |
| @@ -134,7 +100,7 @@ static av_cold int svc_encode_init(AVCodecContext *avctx) · 5 unmodified lines | |||
| 134 | (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level); | 100 | (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_LEVEL, &log_level); |
| 135 | 101 | ||
| 136 | // Set the logging callback function to one that uses av_log() (see implementation above). | 102 | // Set the logging callback function to one that uses av_log() (see implementation above). |
| 137 | callback_function = (WelsTraceCallback) libopenh264_trace_callback; | 103 | callback_function = (WelsTraceCallback) ff_libopenh264_trace_callback; |
| 138 | (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK, (void *)&callback_function); | 104 | (*s->encoder)->SetOption(s->encoder, ENCODER_OPTION_TRACE_CALLBACK, (void *)&callback_function); |
| 139 | 105 | ||
| 140 | // Set the AVCodecContext as the libopenh264 callback context so that it can be passed to av_log(). | 106 | // Set the AVCodecContext as the libopenh264 callback context so that it can be passed to av_log(). |
| @@ -28,8 +28,8 @@ · 27 unmodified lines | |||
| 28 | #include "libavutil/version.h" | 28 | #include "libavutil/version.h" |
| 29 | 29 | ||
| 30 | #define LIBAVCODEC_VERSION_MAJOR 57 | 30 | #define LIBAVCODEC_VERSION_MAJOR 57 |
| 31 | #define LIBAVCODEC_VERSION_MINOR 24 | 31 | #define LIBAVCODEC_VERSION_MINOR 25 |
| 32 | #define LIBAVCODEC_VERSION_MICRO 2 | 32 | #define LIBAVCODEC_VERSION_MICRO 0 |
| 33 | 33 | ||
| 34 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | 34 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |
| 35 | LIBAVCODEC_VERSION_MINOR, \ | 35 | LIBAVCODEC_VERSION_MINOR, \ |