summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2006-07-06 15:04:46 +0000
committerMichael Niedermayer <michaelni@gmx.at>2006-07-06 15:04:46 +0000
commit748c2fca7e4d99357c234936aa71212a6282be36 (patch)
treedd31be48f45e433c1e6b9c002553a2f4191de893
parent06fcf56c50eb6194270656ac8c4fddb250b14eab (diff)
AVBitStreamFilter (some thingy which can modify the bitstream like add or remove global headers or change the headers or ...)
Originally committed as revision 5643 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r--ffmpeg.c85
-rw-r--r--libavcodec/Makefile4
-rw-r--r--libavcodec/allcodecs.c3
-rw-r--r--libavcodec/avcodec.h31
-rw-r--r--libavcodec/bitstream_filter.c96
-rw-r--r--libavcodec/parser.c1
6 files changed, 212 insertions, 8 deletions
diff --git a/ffmpeg.c b/ffmpeg.c
index 717262e265..a005d7fc66 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -250,6 +250,9 @@ const char **opt_names=NULL;
int opt_name_count=0;
AVCodecContext *avctx_opts;
+static AVBitStreamFilterContext *video_bitstream_filters=NULL;
+static AVBitStreamFilterContext *audio_bitstream_filters=NULL;
+static AVBitStreamFilterContext *bitstream_filters[MAX_FILES][MAX_STREAMS];
#define DEFAULT_PASS_LOGFILENAME "ffmpeg2pass"
@@ -445,6 +448,25 @@ get_sync_ipts(const AVOutputStream *ost)
return (double)(ist->pts + input_files_ts_offset[ist->file_index] - start_time)/AV_TIME_BASE;
}
+static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){
+ while(bsfc){
+ AVPacket new_pkt= *pkt;
+ int a= av_bitstream_filter_filter(bsfc, avctx, NULL,
+ &new_pkt.data, &new_pkt.size,
+ pkt->data, pkt->size,
+ pkt->flags & PKT_FLAG_KEY);
+ if(a){
+ av_free_packet(pkt);
+ new_pkt.destruct= av_destruct_packet;
+ }
+ *pkt= new_pkt;
+
+ bsfc= bsfc->next;
+ }
+
+ av_interleaved_write_frame(s, pkt);
+}
+
#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
static void do_audio_out(AVFormatContext *s,
@@ -548,7 +570,7 @@ static void do_audio_out(AVFormatContext *s,
if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
pkt.flags |= PKT_FLAG_KEY;
- av_interleaved_write_frame(s, &pkt);
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
ost->sync_opts += enc->frame_size;
}
@@ -592,7 +614,7 @@ static void do_audio_out(AVFormatContext *s,
if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
pkt.flags |= PKT_FLAG_KEY;
- av_interleaved_write_frame(s, &pkt);
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
}
}
@@ -691,7 +713,7 @@ static void do_subtitle_out(AVFormatContext *s,
else
pkt.pts += 90 * sub->end_display_time;
}
- av_interleaved_write_frame(s, &pkt);
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
}
}
@@ -853,7 +875,7 @@ static void do_video_out(AVFormatContext *s,
if(dec->coded_frame && dec->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
- av_interleaved_write_frame(s, &pkt);
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
enc->coded_frame = old_frame;
} else {
AVFrame big_picture;
@@ -896,7 +918,7 @@ static void do_video_out(AVFormatContext *s,
if(enc->coded_frame && enc->coded_frame->key_frame)
pkt.flags |= PKT_FLAG_KEY;
- av_interleaved_write_frame(s, &pkt);
+ write_frame(s, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
*frame_size = ret;
//fprintf(stderr,"\nFrame: %3d %3d size: %5d type: %d",
// enc->frame_number-1, enc->real_pict_num, ret,
@@ -1317,9 +1339,12 @@ static int output_packet(AVInputStream *ist, int ist_index,
opkt.dts= av_rescale_q(dts + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
}
opkt.flags= pkt->flags;
+
+ //FIXME remove the following 2 lines they shall be replaced by the bitstream filters
if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & PKT_FLAG_KEY))
opkt.destruct= av_destruct_packet;
- av_interleaved_write_frame(os, &opkt);
+
+ write_frame(os, &opkt, ost->st->codec, bitstream_filters[ost->file_index][pkt->stream_index]);
ost->st->codec->frame_number++;
ost->frame_number++;
av_free_packet(&opkt);
@@ -1401,7 +1426,7 @@ static int output_packet(AVInputStream *ist, int ist_index,
pkt.size= ret;
if(enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
pkt.pts= av_rescale_q(enc->coded_frame->pts, enc->time_base, ost->st->time_base);
- av_interleaved_write_frame(os, &pkt);
+ write_frame(os, &pkt, ost->st->codec, bitstream_filters[ost->file_index][pkt.stream_index]);
}
}
}
@@ -2980,6 +3005,9 @@ static void new_video_stream(AVFormatContext *oc)
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
+ bitstream_filters[nb_output_files][oc->nb_streams - 1]= video_bitstream_filters;
+ video_bitstream_filters= NULL;
+
#if defined(HAVE_THREADS)
if(thread_count>1)
avcodec_thread_init(st->codec, thread_count);
@@ -3179,6 +3207,10 @@ static void new_audio_stream(AVFormatContext *oc)
fprintf(stderr, "Could not alloc stream\n");
exit(1);
}
+
+ bitstream_filters[nb_output_files][oc->nb_streams - 1]= audio_bitstream_filters;
+ audio_bitstream_filters= NULL;
+
#if defined(HAVE_THREADS)
if(thread_count>1)
avcodec_thread_init(st->codec, thread_count);
@@ -3885,6 +3917,41 @@ static void opt_target(const char *arg)
}
}
+static void opt_video_bsf(const char *arg)
+{
+ AVBitStreamFilterContext *bsfc= av_bitstream_filter_init(arg); //FIXME split name and args for filter at '='
+ AVBitStreamFilterContext **bsfp;
+
+ if(!bsfc){
+ fprintf(stderr, "Unkown bitstream filter %s\n", arg);
+ exit(1);
+ }
+
+ bsfp= &video_bitstream_filters;
+ while(*bsfp)
+ bsfp= &(*bsfp)->next;
+
+ *bsfp= bsfc;
+}
+
+//FIXME avoid audio - video code duplication
+static void opt_audio_bsf(const char *arg)
+{
+ AVBitStreamFilterContext *bsfc= av_bitstream_filter_init(arg); //FIXME split name and args for filter at '='
+ AVBitStreamFilterContext **bsfp;
+
+ if(!bsfc){
+ fprintf(stderr, "Unkown bitstream filter %s\n", arg);
+ exit(1);
+ }
+
+ bsfp= &audio_bitstream_filters;
+ while(*bsfp)
+ bsfp= &(*bsfp)->next;
+
+ *bsfp= bsfc;
+}
+
static void show_version(void)
{
/* TODO: add function interface to avutil and avformat */
@@ -4069,6 +4136,10 @@ const OptionDef options[] = {
{ "packetsize", OPT_INT | HAS_ARG | OPT_EXPERT, {(void*)&mux_packet_size}, "set packet size", "size" },
{ "muxdelay", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_max_delay}, "set the maximum demux-decode delay", "seconds" },
{ "muxpreload", OPT_FLOAT | HAS_ARG | OPT_EXPERT, {(void*)&mux_preload}, "set the initial demux-decode delay", "seconds" },
+
+ { "absf", HAS_ARG | OPT_AUDIO | OPT_EXPERT, {(void*)opt_audio_bsf}, "", "bitstream filter" },
+ { "vbsf", HAS_ARG | OPT_VIDEO | OPT_EXPERT, {(void*)opt_video_bsf}, "", "bitstream filter" },
+
{ "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
{ NULL, },
};
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 0e28fd3ef8..4ef24562e0 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -17,7 +17,9 @@ OBJS= bitstream.o utils.o mem.o allcodecs.o \
fft.o mdct.o raw.o golomb.o cabac.o\
dpcm.o adx.o faandct.o parser.o g726.o \
vp3dsp.o h264idct.o rangecoder.o pnm.o h263.o msmpeg4.o h263dec.o \
- opt.o
+ opt.o \
+ bitstream_filter.o \
+
HEADERS = avcodec.h
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index ef97b871d3..11d765093a 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -661,5 +661,8 @@ PCM_CODEC(CODEC_ID_ADPCM_SBPRO_2, adpcm_sbpro_2);
av_register_codec_parser(&dvbsub_parser);
#endif
av_register_codec_parser(&aac_parser);
+
+ av_register_bitstream_filter(&dump_extradata_bsf);
+ av_register_bitstream_filter(&remove_extradata_bsf);
}
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 30aad8fadf..1af9901999 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2571,6 +2571,37 @@ extern AVCodecParser dvdsub_parser;
extern AVCodecParser dvbsub_parser;
extern AVCodecParser aac_parser;
+
+typedef struct AVBitStreamFilterContext {
+ struct AVBitStreamFilter *filter;
+ AVCodecParserContext *parser;
+ struct AVBitStreamFilterContext *next;
+} AVBitStreamFilterContext;
+
+
+typedef struct AVBitStreamFilter {
+ const char *name;
+ int (*filter)(AVBitStreamFilterContext *bsfc,
+ AVCodecContext *avctx, const char *args,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe);
+ struct AVBitStreamFilter *next;
+} AVBitStreamFilter;
+
+extern AVBitStreamFilter *av_first_bitstream_filter;
+
+void av_register_bitstream_filter(AVBitStreamFilter *bsf);
+AVBitStreamFilterContext *av_bitstream_filter_init(const char *name);
+int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
+ AVCodecContext *avctx, const char *args,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe);
+void av_bitstream_filter_close(AVBitStreamFilterContext *bsf);
+
+extern AVBitStreamFilter dump_extradata_bsf;
+extern AVBitStreamFilter remove_extradata_bsf;
+
+
/* memory */
void *av_malloc(unsigned int size);
void *av_mallocz(unsigned int size);
diff --git a/libavcodec/bitstream_filter.c b/libavcodec/bitstream_filter.c
new file mode 100644
index 0000000000..8cc75a976b
--- /dev/null
+++ b/libavcodec/bitstream_filter.c
@@ -0,0 +1,96 @@
+
+#include "avcodec.h"
+
+AVBitStreamFilter *first_bitstream_filter= NULL;
+
+void av_register_bitstream_filter(AVBitStreamFilter *bsf){
+ bsf->next = first_bitstream_filter;
+ first_bitstream_filter= bsf;
+}
+
+AVBitStreamFilterContext *av_bitstream_filter_init(const char *name){
+ AVBitStreamFilter *bsf= first_bitstream_filter;
+
+ while(bsf){
+ if(!strcmp(name, bsf->name)){
+ AVBitStreamFilterContext *bsfc= av_mallocz(sizeof(AVBitStreamFilterContext));
+ bsfc->filter= bsf;
+ return bsfc;
+ }
+ bsf= bsf->next;
+ }
+ return NULL;
+}
+
+void av_bitstream_filter_close(AVBitStreamFilterContext *bsfc){
+ av_parser_close(bsfc->parser);
+ av_free(bsfc);
+}
+
+int av_bitstream_filter_filter(AVBitStreamFilterContext *bsfc,
+ AVCodecContext *avctx, const char *args,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe){
+ return bsfc->filter->filter(bsfc, avctx, args, poutbuf, poutbuf_size, buf, buf_size, keyframe);
+}
+
+static int dump_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe){
+ int cmd= args ? *args : 0;
+ /* cast to avoid warning about discarding qualifiers */
+ *poutbuf= (uint8_t *) buf;
+ *poutbuf_size= buf_size;
+ if(avctx->extradata){
+ if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER) && cmd=='a')
+ ||(keyframe && (cmd=='k' || !cmd))
+ ||(cmd=='e')
+ /*||(? && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_BEGIN)*/){
+ int size= buf_size + avctx->extradata_size;
+ *poutbuf_size= size;
+ *poutbuf= av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE);
+
+ memcpy(*poutbuf, avctx->extradata, avctx->extradata_size);
+ memcpy((*poutbuf) + avctx->extradata_size, buf, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int remove_extradata(AVBitStreamFilterContext *bsfc, AVCodecContext *avctx, const char *args,
+ uint8_t **poutbuf, int *poutbuf_size,
+ const uint8_t *buf, int buf_size, int keyframe){
+ int cmd= args ? *args : 0;
+ AVCodecParserContext *s;
+
+ if(!bsfc->parser){
+ bsfc->parser= av_parser_init(avctx->codec_id);
+ }
+ s= bsfc->parser;
+
+ if(s && s->parser->split){
+ if( (((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) || (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)) && cmd=='a')
+ ||(!keyframe && cmd=='k')
+ ||(cmd=='e' || !cmd)
+ ){
+ int i= s->parser->split(avctx, buf, buf_size);
+ buf += i;
+ buf_size -= i;
+ }
+ }
+ *poutbuf= (uint8_t *) buf;
+ *poutbuf_size= buf_size;
+
+ return 0;
+}
+
+AVBitStreamFilter dump_extradata_bsf={
+ "dump_extra",
+ dump_extradata,
+};
+
+AVBitStreamFilter remove_extradata_bsf={
+ "remove_extra",
+ remove_extradata,
+};
diff --git a/libavcodec/parser.c b/libavcodec/parser.c
index 1977dd4943..4944b3a9fc 100644
--- a/libavcodec/parser.c
+++ b/libavcodec/parser.c
@@ -145,6 +145,7 @@ int av_parser_parse(AVCodecParserContext *s,
/**
*
* @return 0 if the output buffer is a subset of the input, 1 if it is allocated and must be freed
+ * @deprecated use AVBitstreamFilter
*/
int av_parser_change(AVCodecParserContext *s,
AVCodecContext *avctx,