Description: Port to ffmpeg 5.0 API Not well-tested since we currently don't build the test suite. . Also closes a presumed memory leak in src/utils/jpgloader-ffmpeg.c:jpeg2yuv() Author: Dennis Filder Last-Update: 2022-06-28 Bug-Debian: https://bugs.debian.org/1004819 --- mediastreamer2-5.3.29/cmake/FindFFMpeg.cmake.orig 2024-02-21 12:02:03.000000000 +0100 +++ mediastreamer2-5.3.29/cmake/FindFFMpeg.cmake 2024-03-09 15:46:23.298516579 +0100 @@ -71,8 +71,11 @@ endif() set(_FFMpeg_CACHE_VARS ${_FFMpeg_REQUIRED_VARS} HAVE_LIBAVCODEC_AVCODEC_H HAVE_LIBSWSCALE_SWSCALE_H + HAVE_FUN_avcodec_alloc_context3 + HAVE_FUN_avcodec_get_context_defaults HAVE_FUN_avcodec_get_context_defaults3 HAVE_FUN_avcodec_open2 + HAVE_FUN_avcodec_encode_video HAVE_FUN_avcodec_encode_video2 HAVE_FUN_av_frame_alloc HAVE_FUN_av_frame_free @@ -145,8 +148,11 @@ else() if(LIBM) list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBM}) endif() + check_symbol_exists(avcodec_alloc_context3 "libavcodec/avcodec.h" HAVE_FUN_avcodec_alloc_context3) + check_symbol_exists(avcodec_get_context_defaults "libavcodec/avcodec.h" HAVE_FUN_avcodec_get_context_defaults) check_symbol_exists(avcodec_get_context_defaults3 "libavcodec/avcodec.h" HAVE_FUN_avcodec_get_context_defaults3) check_symbol_exists(avcodec_open2 "libavcodec/avcodec.h" HAVE_FUN_avcodec_open2) + check_symbol_exists(avcodec_encode_video "libavcodec/avcodec.h" HAVE_FUN_avcodec_encode_video) check_symbol_exists(avcodec_encode_video2 "libavcodec/avcodec.h" HAVE_FUN_avcodec_encode_video2) check_symbol_exists(av_frame_alloc "libavutil/avutil.h;libavutil/frame.h" HAVE_FUN_av_frame_alloc) check_symbol_exists(av_frame_free "libavutil/avutil.h;libavutil/frame.h" HAVE_FUN_av_frame_free) --- mediastreamer2-5.3.29/mediastreamer-config.h.cmake.orig 2024-02-21 12:02:03.000000000 +0100 +++ mediastreamer2-5.3.29/mediastreamer-config.h.cmake 2024-03-09 17:07:32.915468933 +0100 @@ -60,8 +60,11 @@ #cmakedefine HAVE_LIBAVCODEC_AVCODEC_H 1 #cmakedefine HAVE_LIBSWSCALE_SWSCALE_H 1 #cmakedefine HAVE_LIBYUV_H 1 +#cmakedefine HAVE_FUN_avcodec_alloc_context3 +#cmakedefine HAVE_FUN_avcodec_get_context_defaults 1 #cmakedefine HAVE_FUN_avcodec_get_context_defaults3 1 #cmakedefine HAVE_FUN_avcodec_open2 1 +#cmakedefine HAVE_FUN_avcodec_encode_video 1 #cmakedefine HAVE_FUN_avcodec_encode_video2 1 #cmakedefine HAVE_FUN_av_frame_alloc 1 #cmakedefine HAVE_FUN_av_frame_free 1 --- mediastreamer2-5.3.29/src/utils/ffmpeg-priv.h.orig 2024-03-09 15:55:58.335401336 +0100 +++ mediastreamer2-5.3.29/src/utils/ffmpeg-priv.h 2024-03-09 15:56:01.452051119 +0100 @@ -112,12 +112,14 @@ extern "C" { extern "C" { #endif -#ifndef HAVE_FUN_avcodec_encode_video2 +#if defined(HAVE_FUN_avcodec_encode_video) && !defined(HAVE_FUN_avcodec_encode_video2) int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr); #endif -#ifndef HAVE_FUN_avcodec_get_context_defaults3 /**/ +#if defined(HAVE_FUN_avcodec_get_context_defaults) && !defined(HAVE_FUN_avcodec_get_context_defaults3) /**/ int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec); +#endif +#ifndef HAVE_FUN_avcodec_alloc_context3 AVCodecContext *avcodec_alloc_context3(AVCodec *codec); #endif --- mediastreamer2-5.3.29/src/utils/ffmpeg-priv.c.orig 2024-02-21 12:02:03.000000000 +0100 +++ mediastreamer2-5.3.29/src/utils/ffmpeg-priv.c 2024-03-09 15:56:57.378414806 +0100 @@ -21,7 +21,7 @@ #include "ffmpeg-priv.h" -#ifndef HAVE_FUN_avcodec_encode_video2 +#if defined(HAVE_FUN_avcodec_encode_video) && !defined(HAVE_FUN_avcodec_encode_video2) int avcodec_encode_video2(AVCodecContext *avctx, AVPacket *avpkt, const AVFrame *frame, int *got_packet_ptr) { int error = avcodec_encode_video(avctx, avpkt->data, avpkt->size, frame); if (error < 0) { @@ -36,12 +36,14 @@ int avcodec_encode_video2(AVCodecContext } #endif -#ifndef HAVE_FUN_avcodec_get_context_defaults3 /**/ +#if defined(HAVE_FUN_avcodec_get_context_defaults) && !defined(HAVE_FUN_avcodec_get_context_defaults3) /**/ int avcodec_get_context_defaults3(AVCodecContext *s, AVCodec *codec) { avcodec_get_context_defaults(s); return 0; } +#endif +#ifndef HAVE_FUN_avcodec_alloc_context3 /**/ AVCodecContext *avcodec_alloc_context3(AVCodec *codec) { return avcodec_alloc_context(); } --- mediastreamer2-5.3.29/src/videofilters/videodec.c.orig 2024-02-21 12:02:03.000000000 +0100 +++ mediastreamer2-5.3.29/src/videofilters/videodec.c 2024-03-09 16:15:27.685733089 +0100 @@ -47,8 +47,8 @@ extern void ms_ffmpeg_check_init(void); typedef struct DecState { - AVCodecContext av_context; - AVCodec *av_codec; + AVCodecContext *av_contextp; + const AVCodec *av_codec; enum CodecID codec; mblk_t *input; YuvBuf outbuf; @@ -63,11 +63,14 @@ typedef struct DecState { bool_t first_image_decoded; } DecState; +/* + * FIXME: With the ffmpeg 5.0 API this ought to return an error when + * allocation fails. + */ static void dec_init(MSFilter *f, enum CodecID cid) { DecState *s = (DecState *)ms_new0(DecState, 1); ms_ffmpeg_check_init(); - avcodec_get_context_defaults3(&s->av_context, NULL); s->allocator = ms_yuv_buf_allocator_new(); s->av_codec = NULL; s->codec = cid; @@ -83,6 +86,10 @@ static void dec_init(MSFilter *f, enum C if (s->av_codec == NULL) { ms_error("Could not find decoder %i!", s->codec); } + s->av_contextp = avcodec_alloc_context3(s->av_codec); + if (s->av_contextp==NULL){ + ms_error("Could not allocate AVCodecContext!"); + } s->orig = av_frame_alloc(); if (!s->orig) { ms_error("Could not allocate frame"); @@ -118,9 +125,8 @@ static void dec_uninit(MSFilter *f) { av_frame_free(&s->orig); s->orig = NULL; } - if (s->av_context.codec != NULL) { - avcodec_close(&s->av_context); - s->av_context.codec = NULL; + if (s->av_contextp != NULL && s->av_contextp->codec != NULL) { + avcodec_free_context(&s->av_contextp); } ms_yuv_buf_allocator_free(s->allocator); if (s->input != NULL) freemsg(s->input); @@ -159,16 +165,16 @@ static void dec_preprocess(MSFilter *f) s->first_image_decoded = FALSE; ms_average_fps_init(&s->fps, "Video decoder: FPS: %f"); - if (s->av_context.codec == NULL) { + if (s->av_contextp != NULL && s->av_contextp->codec == NULL) { /* we must know picture size before initializing snow decoder*/ #if HAVE_AVCODEC_SNOW if (s->codec != CODEC_ID_SNOW) { #endif - error = avcodec_open2(&s->av_context, s->av_codec, NULL); + error = avcodec_open2(s->av_contextp, s->av_codec, NULL); if (error != 0) ms_error("avcodec_open() failed: %i", error); if (s->codec == CODEC_ID_MPEG4 && s->dci_size > 0) { - s->av_context.extradata = s->dci; - s->av_context.extradata_size = s->dci_size; + s->av_contextp->extradata = s->dci; + s->av_contextp->extradata_size = s->dci_size; } #if HAVE_AVCODEC_SNOW } @@ -258,13 +264,13 @@ static mblk_t *parse_snow_header(DecStat uint32_t h = ntohl(*(uint32_t *)inm->b_rptr); if (!s->snow_initialized) { int error; - s->av_context.width = h >> 16; - s->av_context.height = h & 0xffff; - error = avcodec_open2(&s->av_context, s->av_codec, NULL); + s->av_contextp->width = h >> 16; + s->av_contextp->height = h & 0xffff; + error = avcodec_open2(s->av_contextp, s->av_codec, NULL); if (error != 0) ms_error("avcodec_open() failed for snow: %i", error); else { s->snow_initialized = TRUE; - ms_message("Snow decoder initialized,size=%ix%i", s->av_context.width, s->av_context.height); + ms_message("Snow decoder initialized,size=%ix%i", s->av_contextp->width, s->av_contextp->height); } } inm->b_rptr += 4; @@ -558,7 +564,7 @@ static mblk_t *read_rfc2435_header(DecSt } static mblk_t *get_as_yuvmsg(MSFilter *f, DecState *s, AVFrame *orig) { - AVCodecContext *ctx = &s->av_context; + AVCodecContext *ctx = s->av_contextp; mblk_t *yuv_msg; if (ctx->width == 0 || ctx->height == 0) { @@ -591,7 +597,7 @@ static mblk_t *get_as_yuvmsg(MSFilter *f #endif ms_error("%s: error in ms_sws_scale().", f->desc->name); } - mblk_set_timestamp_info(yuv_msg, (uint32_t)orig->pkt_pts); + mblk_set_timestamp_info(yuv_msg, (uint32_t)orig->pts); return yuv_msg; } /* Bitmasks to select bits of a byte from low side */ @@ -600,7 +606,7 @@ static unsigned char smasks[7] = {0x7f, static void dec_process_frame(MSFilter *f, mblk_t *inm) { DecState *s = (DecState *)f->data; - int got_picture; + int got_picture = 0; /* get a picture from the input queue */ if (f->desc->id == MS_H263_DEC_ID) inm = skip_rfc2429_header(inm); @@ -649,12 +655,27 @@ static void dec_process_frame(MSFilter * pkt.data = frame->b_rptr; pkt.size = remain; pkt.pts = frame_ts; - len = avcodec_decode_video2(&s->av_context, s->orig, &got_picture, &pkt); - - if (len <= 0) { - ms_warning("ms_AVdecoder_process: error %i.", len); - ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_DECODING_ERRORS); - break; + { + int ret1 = avcodec_send_packet(s->av_contextp, &pkt), ret2; + char errmsg[AV_ERROR_MAX_STRING_SIZE]; + if (ret1 < 0) { + av_strerror(ret1, errmsg, sizeof(errmsg)); + ms_warning("ms_AVdecoder_process: avcodec_send_packet failed: %s.",errmsg); + } else { + ret2 = avcodec_receive_frame(s->av_contextp, s->orig); + if (ret2 < 0) { + av_strerror(ret2, errmsg, sizeof(errmsg)); + ms_warning("ms_AVdecoder_process: avcodec_receive_frame failed: %s.",errmsg); + } else { + got_picture=1; + } + } + if (ret1 == 0 && ret2 == 0) + len = pkt.size; + else { + ms_filter_notify_no_arg(f,MS_VIDEO_DECODER_DECODING_ERRORS); + break; + } } if (got_picture) { mblk_t *om = get_as_yuvmsg(f, s, s->orig); --- mediastreamer2-5.3.29/src/videofilters/videoenc.c.orig 2024-02-21 12:02:03.000000000 +0100 +++ mediastreamer2-5.3.29/src/videofilters/videoenc.c 2024-03-09 16:23:29.366456934 +0100 @@ -37,6 +37,9 @@ #include "rfc2429.h" +#include +#include + #if LIBAVCODEC_VERSION_MAJOR >= 57 #ifdef _MSC_VER @@ -109,7 +112,6 @@ void ms_ffmpeg_log_callback(void *ptr, i void ms_ffmpeg_check_init() { if (!avcodec_initialized) { - avcodec_register_all(); avcodec_initialized = TRUE; #ifdef ENABLE_LOG_FFMPEG av_log_set_level(AV_LOG_WARNING); @@ -119,8 +121,8 @@ void ms_ffmpeg_check_init() { } typedef struct EncState { - AVCodecContext av_context; - AVCodec *av_codec; + AVCodecContext *av_contextp; + const AVCodec *av_codec; AVFrame *pict; enum CodecID codec; mblk_t *comp_buf; @@ -223,7 +225,7 @@ static void enc_init(MSFilter *f, enum C s->qmin = 2; s->req_vfu = FALSE; s->framenum = 0; - s->av_context.codec = NULL; + s->av_contextp->codec = NULL; s->vconf_list = get_vconf_list(s); s->vconf = ms_video_find_best_configuration_for_bitrate(s->vconf_list, 500000, ms_factory_get_cpu_count(f->factory)); @@ -246,11 +248,21 @@ static void enc_mjpeg_init(MSFilter *f) enc_init(f, CODEC_ID_MJPEG); } +/* + * FIXME: With the ffmpeg 5.0 API this ought to return an error when + * allocation fails. + */ static void prepare(EncState *s) { - AVCodecContext *c = &s->av_context; + AVCodecContext *c = s->av_contextp; const int max_br_vbv = 128000; - avcodec_get_context_defaults3(c, NULL); + if (s->av_contextp != NULL) + avcodec_free_context(&s->av_contextp); + s->av_contextp = avcodec_alloc_context3(NULL); + if (!s->av_contextp) { + ms_error("Could not allocate AVCodecContext."); + return; + } if (s->codec == CODEC_ID_MJPEG) { ms_message("Codec bitrate set to %i", (int)c->bit_rate); c->width = s->vconf.vsize.width; @@ -306,13 +318,13 @@ static void prepare(EncState *s) { } static void prepare_h263(EncState *s) { - AVCodecContext *c = &s->av_context; + AVCodecContext *c = s->av_contextp; /* we don't use the rtp_callback but use rtp_mode that forces ffmpeg to insert Start Codes as much as possible in the bitstream */ #if LIBAVCODEC_VERSION_INT < ((52 << 16) + (0 << 8) + 0) c->rtp_mode = 1; #endif - c->rtp_payload_size = s->mtu / 2; + av_opt_set_int((struct MpegEncContext *) c->priv_data, "ps", s->mtu/2, 0); if (s->profile == 0) { s->codec = CODEC_ID_H263; } else { @@ -328,7 +340,7 @@ static void prepare_h263(EncState *s) { } static void prepare_mpeg4(EncState *s) { - AVCodecContext *c = &s->av_context; + AVCodecContext *c = s->av_contextp; c->max_b_frames = 0; /*don't use b frames*/ } @@ -360,22 +372,21 @@ static void enc_preprocess(MSFilter *f) ms_error("could not find encoder for codec id %i", s->codec); return; } - error = avcodec_open2(&s->av_context, s->av_codec, NULL); + error = avcodec_open2(s->av_contextp, s->av_codec, NULL); if (error != 0) { ms_error("avcodec_open() failed: %i", error); return; } ms_video_starter_init(&s->starter); - ms_debug("image format is %i.", s->av_context.pix_fmt); - ms_message("qmin=%i qmax=%i", s->av_context.qmin, s->av_context.qmax); + ms_debug("image format is %i.", s->av_contextp->pix_fmt); + ms_message("qmin=%i qmax=%i", s->av_contextp->qmin, s->av_contextp->qmax); s->framenum = 0; } static void enc_postprocess(MSFilter *f) { EncState *s = (EncState *)f->data; - if (s->av_context.codec != NULL) { - avcodec_close(&s->av_context); - s->av_context.codec = NULL; + if (s->av_contextp->codec != NULL) { + avcodec_free_context(&s->av_contextp); } if (s->comp_buf != NULL) { freemsg(s->comp_buf); @@ -445,7 +456,7 @@ static void rfc2190_generate_packets(MSF * MIN(packet->b_rptr+s->mtu,frame->b_wptr));*/ frame->b_rptr = packet->b_wptr = packet->b_rptr + get_gbsc_bytealigned(packet->b_rptr, MIN(packet->b_rptr + s->mtu, frame->b_wptr)); - add_rfc2190_header(&packet, &s->av_context, is_iframe); + add_rfc2190_header(&packet, s->av_contextp, is_iframe); mblk_set_timestamp_info(packet, timestamp); ms_queue_put(f->outputs[0], packet); } @@ -776,8 +787,8 @@ static void split_and_send(MSFilter *f, static void process_frame(MSFilter *f, mblk_t *inm) { EncState *s = (EncState *)f->data; - AVCodecContext *c = &s->av_context; - int error, got_packet; + AVCodecContext *c = s->av_contextp; + int got_packet = 0; mblk_t *comp_buf = s->comp_buf; int comp_buf_sz = (int)(dblk_lim(comp_buf->b_datap) - dblk_base(comp_buf->b_datap)); YuvBuf yuv; @@ -787,7 +798,7 @@ static void process_frame(MSFilter *f, m ms_yuv_buf_init_from_mblk(&yuv, inm); /* convert image if necessary */ av_frame_unref(s->pict); - avpicture_fill((AVPicture *)s->pict, yuv.planes[0], c->pix_fmt, c->width, c->height); + av_image_fill_arrays(s->pict->data, s->pict->linesize, yuv.planes[0],c->pix_fmt,c->width,c->height, 32); /* timestamp used by ffmpeg, unset here */ s->pict->pts = AV_NOPTS_VALUE; @@ -812,10 +823,21 @@ static void process_frame(MSFilter *f, m #endif packet.data = comp_buf->b_wptr; packet.size = comp_buf_sz; - error = avcodec_encode_video2(c, &packet, s->pict, &got_packet); - - if (error < 0) ms_warning("ms_AVencoder_process: error %i.", error); - else if (got_packet) { + { + int ret1 = avcodec_send_frame(c, s->pict), ret2; + char errmsg[AV_ERROR_MAX_STRING_SIZE]; + if (ret1 < 0) { + av_strerror(ret1, errmsg, sizeof(errmsg)); + ms_warning("ms_AVencoder_process: avcodec_send_frame failed: %s.",errmsg); + } else { + ret2 = avcodec_receive_packet(c, &packet); + if (ret2 < 0) { + av_strerror(ret2, errmsg, sizeof(errmsg)); + ms_warning("ms_AVencoder_process: avcodec_receive_packet failed: %s.",errmsg); + } else got_packet=1; + } + } + if (got_packet){ bool_t is_iframe = FALSE; s->framenum++; if (s->framenum == 1) { @@ -838,7 +860,7 @@ static void process_frame(MSFilter *f, m static void enc_process(MSFilter *f) { mblk_t *inm; EncState *s = (EncState *)f->data; - if (s->av_context.codec == NULL) { + if (s->av_contextp != NULL && s->av_contextp->codec == NULL) { ms_queue_flush(f->inputs[0]); return; } @@ -864,7 +886,7 @@ static int enc_set_configuration(MSFilte if (vconf != &s->vconf) memcpy(&s->vconf, vconf, sizeof(MSVideoConfiguration)); if (s->vconf.required_bitrate > s->vconf.bitrate_limit) s->vconf.required_bitrate = s->vconf.bitrate_limit; - if (s->av_context.codec != NULL) { + if (s->av_contextp != NULL && s->av_contextp->codec != NULL) { /* Do not change video size if encoder is running */ if (!ms_video_size_equal(s->vconf.vsize, vsize)) { ms_warning( --- mediastreamer2-5.3.29/src/videofilters/h264dec.cpp.orig 2024-02-21 12:02:03.000000000 +0100 +++ mediastreamer2-5.3.29/src/videofilters/h264dec.cpp 2024-03-09 16:44:34.179604853 +0100 @@ -53,7 +53,7 @@ typedef struct _DecData { MSVideoSize vsize; struct SwsContext *sws_ctx; MSAverageFPS fps; - AVCodecContext av_context; + AVCodecContext *av_contextp; unsigned int packet_num; uint8_t *bitstream; int bitstream_size; @@ -66,18 +66,19 @@ typedef struct _DecData { static void ffmpeg_init(void) { static bool_t done = FALSE; if (!done) { - avcodec_register_all(); done = TRUE; } } static void dec_open(DecData *d) { - AVCodec *codec; int error; - codec = avcodec_find_decoder(CODEC_ID_H264); + const AVCodec *codec = avcodec_find_decoder(CODEC_ID_H264); if (codec == NULL) ms_fatal("Could not find H264 decoder in ffmpeg."); - avcodec_get_context_defaults3(&d->av_context, NULL); - error = avcodec_open2(&d->av_context, codec, NULL); + d->av_contextp = avcodec_alloc_context3(codec); + if (!d->av_contextp) { + ms_fatal("Could not allocate AVCodecContext!"); + } + error=avcodec_open2(d->av_contextp,codec, NULL); if (error != 0) { ms_fatal("avcodec_open() failed."); } @@ -113,7 +114,7 @@ static void dec_preprocess(MSFilter *f) } static void dec_reinit(DecData *d) { - avcodec_close(&d->av_context); + avcodec_free_context(&d->av_contextp); dec_open(d); } @@ -125,7 +126,7 @@ static void dec_postprocess(MSFilter *f) static void dec_uninit(MSFilter *f) { DecData *d = (DecData *)f->data; delete d->unpacker; - avcodec_close(&d->av_context); + avcodec_free_context(&d->av_contextp); if (d->sps) freemsg(d->sps); if (d->pps) freemsg(d->pps); if (d->orig) av_frame_free(&d->orig); @@ -136,7 +137,7 @@ static void dec_uninit(MSFilter *f) { } static mblk_t *get_as_yuvmsg(MSFilter *f, DecData *s, AVFrame *orig) { - AVCodecContext *ctx = &s->av_context; + AVCodecContext *ctx = s->av_contextp; MSPicture pic = {0}; mblk_t *yuv_msg; @@ -162,7 +163,7 @@ static mblk_t *get_as_yuvmsg(MSFilter *f ms_error("%s: error in sws_scale().", f->desc->name); } #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(50, 43, 0) // backward compatibility with Debian Squeeze (6.0) - mblk_set_timestamp_info(yuv_msg, (uint32_t)orig->pkt_pts); + mblk_set_timestamp_info(yuv_msg, (uint32_t)orig->pts); #endif return yuv_msg; } @@ -316,9 +317,25 @@ static void dec_process(MSFilter *f) { #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(50, 43, 0) // backward compatibility with Debian Squeeze (6.0) pkt.pts = frame_ts; #endif - len = avcodec_decode_video2(&d->av_context, d->orig, &got_picture, &pkt); + { + len = -1; + char errmsg[AV_ERROR_MAX_STRING_SIZE]; + int ret1 = avcodec_send_packet(d->av_contextp, &pkt), ret2; + if (ret1 < 0) { + av_strerror(ret1, errmsg, sizeof(errmsg)); + ms_warning("ms_AVdecoder_process: avcodec_send_packet failed: %s.", errmsg); + } else { + ret2 = avcodec_receive_frame(d->av_contextp, d->orig); + if (ret2 < 0) { + av_strerror(ret2, errmsg, sizeof(errmsg)); + ms_warning("ms_AVdecoder_process: avcodec_receive_frame failed: %s.",errmsg); + } else { + got_picture=1; + len = pkt.size; + } + } + } if (len <= 0) { - ms_warning("ms_AVdecoder_process: error %i.", len); ms_filter_notify_no_arg(f, MS_VIDEO_DECODER_DECODING_ERRORS); requestPLI = TRUE; break; --- mediastreamer2-5.3.29/src/utils/jpgloader-ffmpeg.c.orig 2024-02-21 12:02:03.000000000 +0100 +++ mediastreamer2-5.3.29/src/utils/jpgloader-ffmpeg.c 2024-03-09 16:51:07.297475151 +0100 @@ -62,7 +62,7 @@ mblk_t *jpeg2yuv(uint8_t *jpgbuf, int bufsize, MSVideoSize *reqsize) { #if !defined(NO_FFMPEG) && !TARGET_OS_IPHONE /* this code must never be used for iOS */ - AVCodecContext av_context; + AVCodecContext *av_contextp; int got_picture = 0; mblk_t *ret; struct SwsContext *sws_ctx; @@ -71,53 +71,78 @@ mblk_t *jpeg2yuv(uint8_t *jpgbuf, int bu AVCodec *codec = avcodec_find_decoder(CODEC_ID_MJPEG); AVFrame *orig = av_frame_alloc(); + if (orig==NULL){ + ms_error("Could not allocate AVFrame."); + return NULL; + } + if (codec == NULL) { ms_error("Could not find MJPEG decoder in ffmpeg."); + av_frame_free(&orig); return NULL; } - avcodec_get_context_defaults3(&av_context, NULL); - if (avcodec_open2(&av_context, codec, NULL) < 0) { + av_contextp = avcodec_alloc_context3(codec); + if (!av_contextp) { + ms_error("jpeg2yuv: avcodec_alloc_context3 failed"); + av_frame_free(&orig); + return NULL; + } + if (avcodec_open2(av_contextp,codec,NULL)<0){ ms_error("jpeg2yuv: avcodec_open failed"); + av_frame_free(&orig); + avcodec_free_context(&av_contextp); return NULL; } av_init_packet(&pkt); pkt.data = jpgbuf; pkt.size = bufsize; - if (avcodec_decode_video2(&av_context, orig, &got_picture, &pkt) < 0) { - ms_error("jpeg2yuv: avcodec_decode_video failed"); - avcodec_close(&av_context); + int ret1 = avcodec_send_packet(av_contextp, &pkt), ret2; + if (ret1 < 0) { + ms_warning("jpeg2yuv: avcodec_send_packet failed: %s.",av_err2str(ret1)); + av_frame_free(&orig); + avcodec_free_context(&av_contextp); return NULL; + } else { + ret2 = avcodec_receive_frame(av_contextp, orig); + if (ret2 < 0) { + ms_warning("jpeg2yuv: avcodec_receive_frame failed: %s.",av_err2str(ret2)); + av_frame_free(&orig); + avcodec_free_context(&av_contextp); + return NULL; + } } ret = ms_yuv_buf_alloc(&dest, reqsize->width, reqsize->height); /* not using SWS_FAST_BILINEAR because it doesn't play well with * av_context.pix_fmt set to AV_PIX_FMT_YUVJ420P by jpeg decoder */ - sws_ctx = sws_getContext(av_context.width, av_context.height, av_context.pix_fmt, reqsize->width, reqsize->height, + sws_ctx = sws_getContext(av_contextp->width, av_contextp->height, av_contextp->pix_fmt, reqsize->width, reqsize->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL); if (sws_ctx == NULL) { ms_error("jpeg2yuv: ms_sws_getContext() failed."); - avcodec_close(&av_context); + av_frame_free(&orig); + avcodec_free_context(&av_contextp); freemsg(ret); return NULL; } #if LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(0, 9, 0) - if (sws_scale(sws_ctx, (const uint8_t *const *)orig->data, orig->linesize, 0, av_context.height, dest.planes, + if (sws_scale(sws_ctx, (const uint8_t *const *)orig->data, orig->linesize, 0, av_contextp->height, dest.planes, dest.strides) < 0) { #else - if (sws_scale(sws_ctx, (uint8_t **)orig->data, orig->linesize, 0, av_context.height, dest.planes, dest.strides) < + if (sws_scale(sws_ctx, (uint8_t **)orig->data, orig->linesize, 0, av_contextp->height, dest.planes, dest.strides) < 0) { #endif ms_error("jpeg2yuv: ms_sws_scale() failed."); sws_freeContext(sws_ctx); - avcodec_close(&av_context); + av_frame_free(&orig); + avcodec_free_context(&av_contextp); freemsg(ret); return NULL; } sws_freeContext(sws_ctx); av_frame_free(&orig); - avcodec_close(&av_context); + avcodec_context_free(av_contextp); return ret; #elif TARGET_OS_IPHONE MSPicture dest;