mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
lavf: add automatic bitstream filtering; bump version
This solves the problem discussed in https://ffmpeg.org/pipermail/ffmpeg-devel/2015-September/179238.html by allowing AVCodec::write_header to be delayed until after packets have been run through required bitstream filters in order to generate global extradata. It also provides a mechanism by which a muxer can add a bitstream filter to a stream automatically, rather than prompting the user to do so.
This commit is contained in:
parent
7a161b74ad
commit
1f9139b07b
@ -48,6 +48,7 @@ version <next>:
|
||||
- SOFAlizer: virtual binaural acoustics filter
|
||||
- VAAPI VP9 hwaccel
|
||||
- audio high-order multiband parametric equalizer
|
||||
- automatic bitstream filtering
|
||||
|
||||
|
||||
version 2.8:
|
||||
|
@ -15,6 +15,9 @@ libavutil: 2015-08-28
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2015-12-28 - xxxxxxx - lavf 57.21.100 - avformat.h
|
||||
Add automatic bitstream filtering; add av_apply_bitstream_filters()
|
||||
|
||||
2015-12-22 - xxxxxxx - lavfi 6.21.101 - avfilter.h
|
||||
Deprecate avfilter_link_set_closed().
|
||||
Applications are not supposed to mess with links,
|
||||
|
@ -600,6 +600,29 @@ typedef struct AVOutputFormat {
|
||||
*/
|
||||
int (*free_device_capabilities)(struct AVFormatContext *s, struct AVDeviceCapabilitiesQuery *caps);
|
||||
enum AVCodecID data_codec; /**< default data codec */
|
||||
/**
|
||||
* Initialize format. May allocate data here, and set any AVFormatContext or
|
||||
* AVStream parameters that need to be set before packets are sent.
|
||||
* This method must not write output.
|
||||
*
|
||||
* Any allocations made here must be freed in deinit().
|
||||
*/
|
||||
int (*init)(struct AVFormatContext *);
|
||||
/**
|
||||
* Deinitialize format. If present, this is called whenever the muxer is being
|
||||
* destroyed, regardless of whether or not the header has been written.
|
||||
*
|
||||
* If a trailer is being written, this is called after write_trailer().
|
||||
*
|
||||
* This is called if init() fails as well.
|
||||
*/
|
||||
void (*deinit)(struct AVFormatContext *);
|
||||
/**
|
||||
* Set up any necessary bitstream filtering and extract any extra data needed
|
||||
* for the global header.
|
||||
* Return 0 if more packets from this stream must be checked; 1 if not.
|
||||
*/
|
||||
int (*check_bitstream)(struct AVFormatContext *, const AVPacket *pkt);
|
||||
} AVOutputFormat;
|
||||
/**
|
||||
* @}
|
||||
|
@ -117,6 +117,11 @@ struct AVFormatInternal {
|
||||
int inject_global_side_data;
|
||||
|
||||
int avoid_negative_ts_use_pts;
|
||||
|
||||
/**
|
||||
* Whether or not a header has already been written
|
||||
*/
|
||||
int header_written;
|
||||
};
|
||||
|
||||
struct AVStreamInternal {
|
||||
@ -125,6 +130,18 @@ struct AVStreamInternal {
|
||||
* from dts.
|
||||
*/
|
||||
int reorder;
|
||||
|
||||
/**
|
||||
* bitstream filter to run on stream
|
||||
* - encoding: Set by muxer using ff_stream_add_bitstream_filter
|
||||
* - decoding: unused
|
||||
*/
|
||||
AVBitStreamFilterContext *bsfc;
|
||||
|
||||
/**
|
||||
* Whether or not check_bitstream should still be run on each packet
|
||||
*/
|
||||
int bitstream_checked;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
@ -405,6 +405,11 @@ FF_ENABLE_DEPRECATION_WARNINGS
|
||||
*options = tmp;
|
||||
}
|
||||
|
||||
if (s->oformat->init && (ret = s->oformat->init(s)) < 0) {
|
||||
s->oformat->deinit(s);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -456,7 +461,7 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
|
||||
if ((ret = init_muxer(s, options)) < 0)
|
||||
return ret;
|
||||
|
||||
if (s->oformat->write_header) {
|
||||
if (s->oformat->write_header && !s->oformat->check_bitstream) {
|
||||
ret = s->oformat->write_header(s);
|
||||
if (ret >= 0 && s->pb && s->pb->error < 0)
|
||||
ret = s->pb->error;
|
||||
@ -464,6 +469,7 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options)
|
||||
return ret;
|
||||
if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
|
||||
avio_flush(s->pb);
|
||||
s->internal->header_written = 1;
|
||||
}
|
||||
|
||||
if ((ret = init_pts(s)) < 0)
|
||||
@ -668,6 +674,18 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
}
|
||||
|
||||
did_split = av_packet_split_side_data(pkt);
|
||||
|
||||
if (!s->internal->header_written && s->oformat->write_header) {
|
||||
ret = s->oformat->write_header(s);
|
||||
if (ret >= 0 && s->pb && s->pb->error < 0)
|
||||
ret = s->pb->error;
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
|
||||
avio_flush(s->pb);
|
||||
s->internal->header_written = 1;
|
||||
}
|
||||
|
||||
if ((pkt->flags & AV_PKT_FLAG_UNCODED_FRAME)) {
|
||||
AVFrame *frame = (AVFrame *)pkt->data;
|
||||
av_assert0(pkt->size == UNCODED_FRAME_PACKET_SIZE);
|
||||
@ -684,7 +702,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt)
|
||||
ret = s->pb->error;
|
||||
}
|
||||
|
||||
|
||||
fail:
|
||||
if (did_split)
|
||||
av_packet_merge_side_data(pkt);
|
||||
|
||||
@ -1021,6 +1039,17 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
|
||||
ret = AVERROR(EINVAL);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (s->oformat->check_bitstream) {
|
||||
if (!st->internal->bitstream_checked) {
|
||||
if ((ret = s->oformat->check_bitstream(s, pkt)) < 0)
|
||||
goto fail;
|
||||
else if (ret == 1)
|
||||
st->internal->bitstream_checked = 1;
|
||||
}
|
||||
}
|
||||
|
||||
av_apply_bitstream_filters(st->codec, pkt, st->internal->bsfc);
|
||||
} else {
|
||||
av_log(s, AV_LOG_TRACE, "av_interleaved_write_frame FLUSH\n");
|
||||
flush = 1;
|
||||
@ -1077,14 +1106,28 @@ int av_write_trailer(AVFormatContext *s)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!s->internal->header_written && s->oformat->write_header) {
|
||||
ret = s->oformat->write_header(s);
|
||||
if (ret >= 0 && s->pb && s->pb->error < 0)
|
||||
ret = s->pb->error;
|
||||
if (ret < 0)
|
||||
goto fail;
|
||||
if (s->flush_packets && s->pb && s->pb->error >= 0 && s->flags & AVFMT_FLAG_FLUSH_PACKETS)
|
||||
avio_flush(s->pb);
|
||||
s->internal->header_written = 1;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (s->oformat->write_trailer)
|
||||
if ((s->internal->header_written || !s->oformat->write_header) && s->oformat->write_trailer)
|
||||
if (ret >= 0) {
|
||||
ret = s->oformat->write_trailer(s);
|
||||
} else {
|
||||
s->oformat->write_trailer(s);
|
||||
}
|
||||
|
||||
if (s->oformat->deinit)
|
||||
s->oformat->deinit(s);
|
||||
|
||||
if (s->pb)
|
||||
avio_flush(s->pb);
|
||||
if (ret == 0)
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 57
|
||||
#define LIBAVFORMAT_VERSION_MINOR 20
|
||||
#define LIBAVFORMAT_VERSION_MINOR 21
|
||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user