diff options
Diffstat (limited to 'libavformat')
-rw-r--r-- | libavformat/avformat.h | 11 | ||||
-rw-r--r-- | libavformat/utils.c | 49 |
2 files changed, 60 insertions, 0 deletions
diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 32bed018ef..39aedb5c6d 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -2764,6 +2764,17 @@ int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, int avformat_queue_attached_pictures(AVFormatContext *s); +/** + * Apply a list of bitstream filters to a packet. + * + * @param codec AVCodecContext, usually from an AVStream + * @param pkt the packet to apply filters to + * @param bsfc a NULL-terminated list of filters to apply + * @return >=0 on success; + * AVERROR code on failure + */ +int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt, + AVBitStreamFilterContext *bsfc); /** * @} diff --git a/libavformat/utils.c b/libavformat/utils.c index 2f864c682a..7e101a4fd3 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -4650,3 +4650,52 @@ uint8_t *av_stream_new_side_data(AVStream *st, enum AVPacketSideDataType type, sd->size = size; return data; } + +int av_apply_bitstream_filters(AVCodecContext *codec, AVPacket *pkt, + AVBitStreamFilterContext *bsfc) +{ + int ret = 0; + while (bsfc) { + AVPacket new_pkt = *pkt; + int a = av_bitstream_filter_filter(bsfc, codec, NULL, + &new_pkt.data, &new_pkt.size, + pkt->data, pkt->size, + pkt->flags & AV_PKT_FLAG_KEY); + if(a == 0 && new_pkt.data != pkt->data) { + uint8_t *t = av_malloc(new_pkt.size + AV_INPUT_BUFFER_PADDING_SIZE); //the new should be a subset of the old so cannot overflow + if (t) { + memcpy(t, new_pkt.data, new_pkt.size); + memset(t + new_pkt.size, 0, AV_INPUT_BUFFER_PADDING_SIZE); + new_pkt.data = t; + new_pkt.buf = NULL; + a = 1; + } else { + a = AVERROR(ENOMEM); + } + } + if (a > 0) { + new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, + av_buffer_default_free, NULL, 0); + if (new_pkt.buf) { + pkt->side_data = NULL; + pkt->side_data_elems = 0; + av_packet_unref(pkt); + } else { + av_freep(&new_pkt.data); + a = AVERROR(ENOMEM); + } + } + if (a < 0) { + av_log(codec, AV_LOG_ERROR, + "Failed to open bitstream filter %s for stream %d with codec %s", + bsfc->filter->name, pkt->stream_index, + codec->codec ? codec->codec->name : "copy"); + ret = a; + break; + } + *pkt = new_pkt; + + bsfc = bsfc->next; + } + return ret; +} |