diff options
-rw-r--r-- | audio/decode/ad_lavc.c | 8 | ||||
-rw-r--r-- | audio/decode/ad_spdif.c | 15 | ||||
-rw-r--r-- | common/av_common.c | 24 | ||||
-rw-r--r-- | common/av_common.h | 1 | ||||
-rw-r--r-- | common/recorder.c | 16 | ||||
-rw-r--r-- | sub/lavc_conv.c | 28 | ||||
-rw-r--r-- | sub/sd_lavc.c | 11 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 16 |
8 files changed, 85 insertions, 34 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 6ae7d80bf5..cdb86c3507 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -46,6 +46,7 @@ struct priv { AVCodecContext *avctx; AVFrame *avframe; + AVPacket *avpkt; struct mp_chmap force_channel_map; uint32_t skip_samples, trim_samples; bool preroll_done; @@ -104,6 +105,7 @@ static bool init(struct mp_filter *da, struct mp_codec_params *codec, lavc_context = avcodec_alloc_context3(lavc_codec); ctx->avctx = lavc_context; ctx->avframe = av_frame_alloc(); + ctx->avpkt = av_packet_alloc(); lavc_context->codec_type = AVMEDIA_TYPE_AUDIO; lavc_context->codec_id = lavc_codec->id; lavc_context->pkt_timebase = ctx->codec_timebase; @@ -160,6 +162,7 @@ static void destroy(struct mp_filter *da) avcodec_free_context(&ctx->avctx); av_frame_free(&ctx->avframe); + mp_free_av_packet(&ctx->avpkt); } static void reset(struct mp_filter *da) @@ -185,10 +188,9 @@ static int send_packet(struct mp_filter *da, struct demux_packet *mpkt) if (mpkt && priv->next_pts == MP_NOPTS_VALUE) priv->next_pts = mpkt->pts; - AVPacket pkt; - mp_set_av_packet(&pkt, mpkt, &priv->codec_timebase); + mp_set_av_packet(priv->avpkt, mpkt, &priv->codec_timebase); - int ret = avcodec_send_packet(avctx, mpkt ? &pkt : NULL); + int ret = avcodec_send_packet(avctx, mpkt ? priv->avpkt : NULL); if (ret < 0) MP_ERR(da, "Error decoding audio.\n"); return ret; diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index 520803c4b0..3b799660c1 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -41,6 +41,7 @@ struct spdifContext { struct mp_log *log; enum AVCodecID codec_id; AVFormatContext *lavf_ctx; + AVPacket *avpkt; int out_buffer_len; uint8_t out_buffer[OUTBUF_SIZE]; bool need_close; @@ -82,6 +83,7 @@ static void destroy(struct mp_filter *da) avformat_free_context(lavf_ctx); spdif_ctx->lavf_ctx = NULL; } + mp_free_av_packet(&spdif_ctx->avpkt); } static void determine_codec_params(struct mp_filter *da, AVPacket *pkt, @@ -295,15 +297,14 @@ static void process(struct mp_filter *da) struct mp_aframe *out = NULL; double pts = mpkt->pts; - AVPacket pkt; - mp_set_av_packet(&pkt, mpkt, NULL); - pkt.pts = pkt.dts = 0; + mp_set_av_packet(spdif_ctx->avpkt, mpkt, NULL); + spdif_ctx->avpkt->pts = spdif_ctx->avpkt->dts = 0; if (!spdif_ctx->lavf_ctx) { - if (init_filter(da, &pkt) < 0) + if (init_filter(da, spdif_ctx->avpkt) < 0) goto done; } spdif_ctx->out_buffer_len = 0; - int ret = av_write_frame(spdif_ctx->lavf_ctx, &pkt); + int ret = av_write_frame(spdif_ctx->lavf_ctx, spdif_ctx->avpkt); avio_flush(spdif_ctx->lavf_ctx->pb); if (ret < 0) { MP_ERR(da, "spdif mux error: '%s'\n", mp_strerror(AVUNERROR(ret))); @@ -424,6 +425,10 @@ static struct mp_decoder *create(struct mp_filter *parent, talloc_free(da); return NULL; } + + spdif_ctx->avpkt = av_packet_alloc(); + MP_HANDLE_OOM(spdif_ctx->avpkt); + return &spdif_ctx->public; } diff --git a/common/av_common.c b/common/av_common.c index 8b5a3970d0..db31988c1b 100644 --- a/common/av_common.c +++ b/common/av_common.c @@ -196,7 +196,11 @@ double mp_pts_from_av(int64_t av_pts, AVRational *tb) // Set duration field only if tb is set. void mp_set_av_packet(AVPacket *dst, struct demux_packet *mpkt, AVRational *tb) { - av_init_packet(dst); + dst->side_data = NULL; + dst->side_data_elems = 0; + dst->buf = NULL; + av_packet_unref(dst); + dst->data = mpkt ? mpkt->buffer : NULL; dst->size = mpkt ? mpkt->len : 0; /* Some codecs (ZeroCodec, some cases of PNG) may want keyframe info @@ -394,3 +398,21 @@ int mp_set_avopts_pos(struct mp_log *log, void *avobj, void *posargs, char **kv) } return success; } + +/** + * Must be used to free an AVPacket that was used with mp_set_av_packet(). + * + * We have a particular pattern where we "borrow" buffers and set them + * into an AVPacket to pass data to ffmpeg without extra copies. + * This applies to buf and side_data, so this function clears them before + * freeing. + */ +void mp_free_av_packet(AVPacket **pkt) +{ + if (*pkt) { + (*pkt)->side_data = NULL; + (*pkt)->side_data_elems = 0; + (*pkt)->buf = NULL; + } + av_packet_free(pkt); +} diff --git a/common/av_common.h b/common/av_common.h index 1b3e468884..dd5e88e003 100644 --- a/common/av_common.h +++ b/common/av_common.h @@ -50,5 +50,6 @@ void mp_set_avdict(struct AVDictionary **dict, char **kv); void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d); int mp_set_avopts(struct mp_log *log, void *avobj, char **kv); int mp_set_avopts_pos(struct mp_log *log, void *avobj, void *posargs, char **kv); +void mp_free_av_packet(AVPacket **pkt); #endif diff --git a/common/recorder.c b/common/recorder.c index 0cbc81d51c..cee837ba24 100644 --- a/common/recorder.c +++ b/common/recorder.c @@ -64,6 +64,7 @@ struct mp_recorder_sink { struct mp_recorder *owner; struct sh_stream *sh; AVStream *av_stream; + AVPacket *avpkt; double max_out_pts; bool discont; bool proper_eof; @@ -82,10 +83,11 @@ static int add_stream(struct mp_recorder *priv, struct sh_stream *sh) .owner = priv, .sh = sh, .av_stream = avformat_new_stream(priv->mux, NULL), + .avpkt = av_packet_alloc(), .max_out_pts = MP_NOPTS_VALUE, }; - if (!rst->av_stream) + if (!rst->av_stream || !rst->avpkt) return -1; AVCodecParameters *avp = mp_codec_params_to_av(sh->codec); @@ -237,15 +239,14 @@ static void mux_packet(struct mp_recorder_sink *rst, rst->max_out_pts = MP_PTS_MAX(rst->max_out_pts, pkt->pts); - AVPacket avpkt; - mp_set_av_packet(&avpkt, &mpkt, &rst->av_stream->time_base); + mp_set_av_packet(rst->avpkt, &mpkt, &rst->av_stream->time_base); - avpkt.stream_index = rst->av_stream->index; + rst->avpkt->stream_index = rst->av_stream->index; - if (avpkt.duration < 0 && rst->sh->type != STREAM_SUB) - avpkt.duration = 0; + if (rst->avpkt->duration < 0 && rst->sh->type != STREAM_SUB) + rst->avpkt->duration = 0; - AVPacket *new_packet = av_packet_clone(&avpkt); + AVPacket *new_packet = av_packet_clone(rst->avpkt); if (!new_packet) { MP_ERR(priv, "Failed to allocate packet.\n"); return; @@ -319,6 +320,7 @@ void mp_recorder_destroy(struct mp_recorder *priv) for (int n = 0; n < priv->num_streams; n++) { struct mp_recorder_sink *rst = priv->streams[n]; mux_packets(rst); + mp_free_av_packet(&rst->avpkt); } if (av_write_trailer(priv->mux) < 0) diff --git a/sub/lavc_conv.c b/sub/lavc_conv.c index d9f628492c..8e26c41237 100644 --- a/sub/lavc_conv.c +++ b/sub/lavc_conv.c @@ -34,6 +34,8 @@ struct lavc_conv { struct mp_log *log; AVCodecContext *avctx; + AVPacket *avpkt; + AVPacket *avpkt_vtt; char *codec; char *extradata; AVSubtitle cur; @@ -84,6 +86,11 @@ struct lavc_conv *lavc_conv_create(struct mp_log *log, const char *codec_name, if (mp_lavc_set_extradata(avctx, extradata, extradata_len) < 0) goto error; + priv->avpkt = av_packet_alloc(); + priv->avpkt_vtt = av_packet_alloc(); + if (!priv->avpkt || !priv->avpkt_vtt) + goto error; + #if LIBAVCODEC_VERSION_MAJOR < 59 av_dict_set(&opts, "sub_text_format", "ass", 0); #endif @@ -107,6 +114,8 @@ struct lavc_conv *lavc_conv_create(struct mp_log *log, const char *codec_name, MP_FATAL(priv, "Could not open libavcodec subtitle converter\n"); av_dict_free(&opts); av_free(avctx); + mp_free_av_packet(&priv->avpkt); + mp_free_av_packet(&priv->avpkt_vtt); talloc_free(priv); return NULL; } @@ -224,26 +233,25 @@ char **lavc_conv_decode(struct lavc_conv *priv, struct demux_packet *packet, double *sub_pts, double *sub_duration) { AVCodecContext *avctx = priv->avctx; - AVPacket pkt; - AVPacket parsed_pkt = {0}; + AVPacket *curr_pkt = priv->avpkt; int ret, got_sub; int num_cur = 0; avsubtitle_free(&priv->cur); - mp_set_av_packet(&pkt, packet, &avctx->time_base); - if (pkt.pts < 0) - pkt.pts = 0; + mp_set_av_packet(priv->avpkt, packet, &avctx->time_base); + if (priv->avpkt->pts < 0) + priv->avpkt->pts = 0; if (strcmp(priv->codec, "webvtt-webm") == 0) { - if (parse_webvtt(&pkt, &parsed_pkt) < 0) { + if (parse_webvtt(priv->avpkt, priv->avpkt_vtt) < 0) { MP_ERR(priv, "Error parsing subtitle\n"); goto done; } - pkt = parsed_pkt; + curr_pkt = priv->avpkt_vtt; } - ret = avcodec_decode_subtitle2(avctx, &priv->cur, &got_sub, &pkt); + ret = avcodec_decode_subtitle2(avctx, &priv->cur, &got_sub, curr_pkt); if (ret < 0) { MP_ERR(priv, "Error decoding subtitle\n"); } else if (got_sub) { @@ -266,7 +274,7 @@ char **lavc_conv_decode(struct lavc_conv *priv, struct demux_packet *packet, } done: - av_packet_unref(&parsed_pkt); + av_packet_unref(priv->avpkt_vtt); MP_TARRAY_APPEND(priv, priv->cur_list, num_cur, NULL); return priv->cur_list; } @@ -280,5 +288,7 @@ void lavc_conv_uninit(struct lavc_conv *priv) { avsubtitle_free(&priv->cur); avcodec_free_context(&priv->avctx); + mp_free_av_packet(&priv->avpkt); + mp_free_av_packet(&priv->avpkt_vtt); talloc_free(priv); } diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c index ce0ef11a0a..7b0d0dfe38 100644 --- a/sub/sd_lavc.c +++ b/sub/sd_lavc.c @@ -59,6 +59,7 @@ struct seekpoint { struct sd_lavc_priv { AVCodecContext *avctx; + AVPacket *avpkt; AVRational pkt_timebase; struct sub subs[MAX_QUEUE]; // most recent event first struct sub_bitmap *outbitmaps; @@ -97,6 +98,9 @@ static int init(struct sd *sd) ctx = avcodec_alloc_context3(sub_codec); if (!ctx) goto error; + priv->avpkt = av_packet_alloc(); + if (!priv->avpkt) + goto error; mp_lavc_set_extradata(ctx, sd->codec->extradata, sd->codec->extradata_size); priv->pkt_timebase = mp_get_codec_timebase(sd->codec); ctx->pkt_timebase = priv->pkt_timebase; @@ -112,6 +116,7 @@ static int init(struct sd *sd) error: MP_FATAL(sd, "Could not open libavcodec subtitle decoder\n"); avcodec_free_context(&ctx); + mp_free_av_packet(&priv->avpkt); talloc_free(priv); return -1; } @@ -298,7 +303,6 @@ static void decode(struct sd *sd, struct demux_packet *packet) double endpts = MP_NOPTS_VALUE; double duration = packet->duration; AVSubtitle sub; - AVPacket pkt; // libavformat sets duration==0, even if the duration is unknown. Some files // also have actually subtitle packets with duration explicitly set to 0 @@ -311,7 +315,7 @@ static void decode(struct sd *sd, struct demux_packet *packet) if (pts == MP_NOPTS_VALUE) MP_WARN(sd, "Subtitle with unknown start time.\n"); - mp_set_av_packet(&pkt, packet, &priv->pkt_timebase); + mp_set_av_packet(priv->avpkt, packet, &priv->pkt_timebase); if (ctx->codec_id == AV_CODEC_ID_DVB_TELETEXT) { char page[4]; @@ -320,7 +324,7 @@ static void decode(struct sd *sd, struct demux_packet *packet) } int got_sub; - int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, &pkt); + int res = avcodec_decode_subtitle2(ctx, &sub, &got_sub, priv->avpkt); if (res < 0 || !got_sub) return; @@ -588,6 +592,7 @@ static void uninit(struct sd *sd) for (int n = 0; n < MAX_QUEUE; n++) clear_sub(&priv->subs[n]); avcodec_free_context(&priv->avctx); + mp_free_av_packet(&priv->avpkt); talloc_free(priv); } diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index c65d9d708a..5e8bf40a66 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -173,6 +173,7 @@ typedef struct lavc_ctx { struct mp_codec_params *codec; AVCodecContext *avctx; AVFrame *pic; + AVPacket *avpkt; bool use_hwdec; struct hwdec_info hwdec; // valid only if use_hwdec==true AVRational codec_timebase; @@ -651,6 +652,10 @@ static void init_avctx(struct mp_filter *vd) if (!ctx->pic) goto error; + ctx->avpkt = av_packet_alloc(); + if (!ctx->avpkt) + goto error; + if (ctx->use_hwdec) { avctx->opaque = vd; avctx->thread_count = 1; @@ -752,9 +757,8 @@ static void init_avctx(struct mp_filter *vd) // x264 build number (encoded in a SEI element), needed to enable a // workaround for broken 4:4:4 streams produced by older x264 versions. if (lavc_codec->id == AV_CODEC_ID_H264 && c->first_packet) { - AVPacket avpkt; - mp_set_av_packet(&avpkt, c->first_packet, &ctx->codec_timebase); - avcodec_send_packet(avctx, &avpkt); + mp_set_av_packet(ctx->avpkt, c->first_packet, &ctx->codec_timebase); + avcodec_send_packet(avctx, ctx->avpkt); avcodec_receive_frame(avctx, ctx->pic); av_frame_unref(ctx->pic); avcodec_flush_buffers(ctx->avctx); @@ -802,6 +806,7 @@ static void uninit_avctx(struct mp_filter *vd) flush_all(vd); av_frame_free(&ctx->pic); + mp_free_av_packet(&ctx->avpkt); av_buffer_unref(&ctx->cached_hw_frames_ctx); avcodec_free_context(&ctx->avctx); @@ -1067,10 +1072,9 @@ static int send_packet(struct mp_filter *vd, struct demux_packet *pkt) if (avctx->skip_frame == AVDISCARD_ALL) return 0; - AVPacket avpkt; - mp_set_av_packet(&avpkt, pkt, &ctx->codec_timebase); + mp_set_av_packet(ctx->avpkt, pkt, &ctx->codec_timebase); - int ret = avcodec_send_packet(avctx, pkt ? &avpkt : NULL); + int ret = avcodec_send_packet(avctx, pkt ? ctx->avpkt : NULL); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) return ret; |