Commit 90ad92b3 authored by Michael Niedermayer's avatar Michael Niedermayer

support changing in bitstream global headers into extradata style and back

Originally committed as revision 4395 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 718b27a7
...@@ -254,6 +254,7 @@ static int video_sync_method= 1; ...@@ -254,6 +254,7 @@ static int video_sync_method= 1;
static int audio_sync_method= 0; static int audio_sync_method= 0;
static int copy_ts= 0; static int copy_ts= 0;
static int opt_shortest = 0; // static int opt_shortest = 0; //
static int video_global_header = 0;
static int rate_emu = 0; static int rate_emu = 0;
...@@ -1396,8 +1397,6 @@ static int output_packet(AVInputStream *ist, int ist_index, ...@@ -1396,8 +1397,6 @@ static int output_packet(AVInputStream *ist, int ist_index,
} }
opkt.stream_index= ost->index; opkt.stream_index= ost->index;
opkt.data= data_buf;
opkt.size= data_size;
if(pkt->pts != AV_NOPTS_VALUE) if(pkt->pts != AV_NOPTS_VALUE)
opkt.pts= av_rescale_q(av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base); opkt.pts= av_rescale_q(av_rescale_q(pkt->pts, ist->st->time_base, AV_TIME_BASE_Q) + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
else else
...@@ -1412,9 +1411,12 @@ static int output_packet(AVInputStream *ist, int ist_index, ...@@ -1412,9 +1411,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.dts= av_rescale_q(dts + input_files_ts_offset[ist->file_index], AV_TIME_BASE_Q, ost->st->time_base);
} }
opkt.flags= pkt->flags; opkt.flags= pkt->flags;
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); av_interleaved_write_frame(os, &opkt);
ost->st->codec.frame_number++; ost->st->codec.frame_number++;
ost->frame_number++; ost->frame_number++;
av_free_packet(&opkt);
} }
} }
} }
...@@ -3187,8 +3189,12 @@ static void new_video_stream(AVFormatContext *oc) ...@@ -3187,8 +3189,12 @@ static void new_video_stream(AVFormatContext *oc)
if(video_codec_tag) if(video_codec_tag)
video_enc->codec_tag= video_codec_tag; video_enc->codec_tag= video_codec_tag;
if (oc->oformat->flags & AVFMT_GLOBALHEADER) if( (video_global_header&1)
|| (video_global_header==0 && (oc->oformat->flags & AVFMT_GLOBALHEADER)))
video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER; video_enc->flags |= CODEC_FLAG_GLOBAL_HEADER;
if(video_global_header&2)
video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
if (video_stream_copy) { if (video_stream_copy) {
st->stream_copy = 1; st->stream_copy = 1;
video_enc->codec_type = CODEC_TYPE_VIDEO; video_enc->codec_type = CODEC_TYPE_VIDEO;
...@@ -4189,6 +4195,7 @@ const OptionDef options[] = { ...@@ -4189,6 +4195,7 @@ const OptionDef options[] = {
{ "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" }, { "threads", HAS_ARG | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
{ "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" }, { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" },
{ "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" },
{ "vglobal", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_global_header}, "video global header storage type", "" },
{ "copyts", OPT_BOOL | OPT_EXPERT, {(void*)&copy_ts}, "copy timestamps" }, { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)&copy_ts}, "copy timestamps" },
{ "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, // { "shortest", OPT_BOOL | OPT_EXPERT, {(void*)&opt_shortest}, "finish encoding within shortest input" }, //
......
...@@ -341,6 +341,7 @@ extern int motion_estimation_method; ...@@ -341,6 +341,7 @@ extern int motion_estimation_method;
#define CODEC_FLAG2_FAST 0x00000001 ///< allow non spec compliant speedup tricks #define CODEC_FLAG2_FAST 0x00000001 ///< allow non spec compliant speedup tricks
#define CODEC_FLAG2_STRICT_GOP 0x00000002 ///< strictly enforce GOP size #define CODEC_FLAG2_STRICT_GOP 0x00000002 ///< strictly enforce GOP size
#define CODEC_FLAG2_NO_OUTPUT 0x00000004 ///< skip bitstream encoding #define CODEC_FLAG2_NO_OUTPUT 0x00000004 ///< skip bitstream encoding
#define CODEC_FLAG2_LOCAL_HEADER 0x00000008 ///< place global headers at every keyframe instead of in extradata
/* Unsupported options : /* Unsupported options :
* Syntax Arithmetic coding (SAC) * Syntax Arithmetic coding (SAC)
...@@ -2322,6 +2323,7 @@ typedef struct AVCodecParser { ...@@ -2322,6 +2323,7 @@ typedef struct AVCodecParser {
uint8_t **poutbuf, int *poutbuf_size, uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size); const uint8_t *buf, int buf_size);
void (*parser_close)(AVCodecParserContext *s); void (*parser_close)(AVCodecParserContext *s);
int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size);
struct AVCodecParser *next; struct AVCodecParser *next;
} AVCodecParser; } AVCodecParser;
...@@ -2334,6 +2336,10 @@ int av_parser_parse(AVCodecParserContext *s, ...@@ -2334,6 +2336,10 @@ int av_parser_parse(AVCodecParserContext *s,
uint8_t **poutbuf, int *poutbuf_size, uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, const uint8_t *buf, int buf_size,
int64_t pts, int64_t dts); int64_t pts, int64_t dts);
int av_parser_change(AVCodecParserContext *s,
AVCodecContext *avctx,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe);
void av_parser_close(AVCodecParserContext *s); void av_parser_close(AVCodecParserContext *s);
extern AVCodecParser mpegvideo_parser; extern AVCodecParser mpegvideo_parser;
......
...@@ -142,6 +142,38 @@ int av_parser_parse(AVCodecParserContext *s, ...@@ -142,6 +142,38 @@ int av_parser_parse(AVCodecParserContext *s,
return index; return index;
} }
int av_parser_change(AVCodecParserContext *s,
AVCodecContext *avctx,
uint8_t **poutbuf, int *poutbuf_size,
const uint8_t *buf, int buf_size, int keyframe){
if(s && s->parser->split){
if((avctx->flags & CODEC_FLAG_GLOBAL_HEADER) && !(avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER)){
int i= s->parser->split(avctx, buf, buf_size);
buf += i;
buf_size -= i;
}
}
*poutbuf= buf;
*poutbuf_size= buf_size;
if(avctx->extradata){
if( (keyframe && (avctx->flags2 & CODEC_FLAG2_LOCAL_HEADER))
/*||(s->pict_type != I_TYPE && (s->flags & PARSER_FLAG_DUMP_EXTRADATA_AT_NOKEY))*/
/*||(? && (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);
return 1;
}
}
return 0;
}
void av_parser_close(AVCodecParserContext *s) void av_parser_close(AVCodecParserContext *s)
{ {
if (s->parser->parser_close) if (s->parser->parser_close)
...@@ -294,7 +326,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s, ...@@ -294,7 +326,7 @@ static void mpegvideo_extract_headers(AVCodecParserContext *s,
int frame_rate_ext_n, frame_rate_ext_d; int frame_rate_ext_n, frame_rate_ext_d;
int picture_structure, top_field_first, repeat_first_field, progressive_frame; int picture_structure, top_field_first, repeat_first_field, progressive_frame;
int horiz_size_ext, vert_size_ext, bit_rate_ext; int horiz_size_ext, vert_size_ext, bit_rate_ext;
//FIXME replace the crap with get_bits()
s->repeat_pict = 0; s->repeat_pict = 0;
buf_end = buf + buf_size; buf_end = buf + buf_size;
while (buf < buf_end) { while (buf < buf_end) {
...@@ -415,6 +447,20 @@ static int mpegvideo_parse(AVCodecParserContext *s, ...@@ -415,6 +447,20 @@ static int mpegvideo_parse(AVCodecParserContext *s,
return next; return next;
} }
static int mpegvideo_split(AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
{
int i;
uint32_t state= -1;
for(i=0; i<buf_size; i++){
state= (state<<8) | buf[i];
if(state != 0x1B3 && state != 0x1B5 && state < 0x200 && state >= 0x100)
return i-4;
}
return 0;
}
void ff_parse_close(AVCodecParserContext *s) void ff_parse_close(AVCodecParserContext *s)
{ {
ParseContext *pc = s->priv_data; ParseContext *pc = s->priv_data;
...@@ -493,6 +539,20 @@ static int mpeg4video_parse(AVCodecParserContext *s, ...@@ -493,6 +539,20 @@ static int mpeg4video_parse(AVCodecParserContext *s,
return next; return next;
} }
static int mpeg4video_split(AVCodecContext *avctx,
const uint8_t *buf, int buf_size)
{
int i;
uint32_t state= -1;
for(i=0; i<buf_size; i++){
state= (state<<8) | buf[i];
if(state == 0x1B3 || state == 0x1B6)
return i-4;
}
return 0;
}
/*************************/ /*************************/
typedef struct MpegAudioParseContext { typedef struct MpegAudioParseContext {
...@@ -768,6 +828,7 @@ AVCodecParser mpegvideo_parser = { ...@@ -768,6 +828,7 @@ AVCodecParser mpegvideo_parser = {
NULL, NULL,
mpegvideo_parse, mpegvideo_parse,
parse1_close, parse1_close,
mpegvideo_split,
}; };
AVCodecParser mpeg4video_parser = { AVCodecParser mpeg4video_parser = {
...@@ -776,6 +837,7 @@ AVCodecParser mpeg4video_parser = { ...@@ -776,6 +837,7 @@ AVCodecParser mpeg4video_parser = {
mpeg4video_parse_init, mpeg4video_parse_init,
mpeg4video_parse, mpeg4video_parse,
parse1_close, parse1_close,
mpeg4video_split,
}; };
AVCodecParser mpegaudio_parser = { AVCodecParser mpegaudio_parser = {
......
...@@ -42,6 +42,7 @@ typedef struct AVPacket { ...@@ -42,6 +42,7 @@ typedef struct AVPacket {
#define PKT_FLAG_KEY 0x0001 #define PKT_FLAG_KEY 0x0001
void av_destruct_packet_nofree(AVPacket *pkt); void av_destruct_packet_nofree(AVPacket *pkt);
void av_destruct_packet(AVPacket *pkt);
/* initialize optional fields of a packet */ /* initialize optional fields of a packet */
static inline void av_init_packet(AVPacket *pkt) static inline void av_init_packet(AVPacket *pkt)
......
...@@ -165,7 +165,7 @@ AVInputFormat *av_find_input_format(const char *short_name) ...@@ -165,7 +165,7 @@ AVInputFormat *av_find_input_format(const char *short_name)
/** /**
* Default packet destructor * Default packet destructor
*/ */
static void av_destruct_packet(AVPacket *pkt) void av_destruct_packet(AVPacket *pkt)
{ {
av_free(pkt->data); av_free(pkt->data);
pkt->data = NULL; pkt->size = 0; pkt->data = NULL; pkt->size = 0;
...@@ -834,7 +834,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) ...@@ -834,7 +834,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
/* select current input stream component */ /* select current input stream component */
st = s->cur_st; st = s->cur_st;
if (st) { if (st) {
if (!st->parser) { if (!st->need_parsing || !st->parser) {
/* no parsing needed: we just output the packet as is */ /* no parsing needed: we just output the packet as is */
/* raw data support */ /* raw data support */
*pkt = s->cur_pkt; *pkt = s->cur_pkt;
...@@ -876,7 +876,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt) ...@@ -876,7 +876,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
/* return the last frames, if any */ /* return the last frames, if any */
for(i = 0; i < s->nb_streams; i++) { for(i = 0; i < s->nb_streams; i++) {
st = s->streams[i]; st = s->streams[i];
if (st->parser) { if (st->parser && st->need_parsing) {
av_parser_parse(st->parser, &st->codec, av_parser_parse(st->parser, &st->codec,
&pkt->data, &pkt->size, &pkt->data, &pkt->size,
NULL, 0, NULL, 0,
...@@ -1742,6 +1742,10 @@ int av_find_stream_info(AVFormatContext *ic) ...@@ -1742,6 +1742,10 @@ int av_find_stream_info(AVFormatContext *ic)
if(!st->codec.time_base.num) if(!st->codec.time_base.num)
st->codec.time_base= st->time_base; st->codec.time_base= st->time_base;
} }
//only for the split stuff
if (!st->parser) {
st->parser = av_parser_init(st->codec.codec_id);
}
} }
for(i=0;i<MAX_STREAMS;i++){ for(i=0;i<MAX_STREAMS;i++){
...@@ -1762,6 +1766,8 @@ int av_find_stream_info(AVFormatContext *ic) ...@@ -1762,6 +1766,8 @@ int av_find_stream_info(AVFormatContext *ic)
if( st->codec.time_base.den >= 1000LL*st->codec.time_base.num if( st->codec.time_base.den >= 1000LL*st->codec.time_base.num
&& duration_count[i]<20 && st->codec.codec_type == CODEC_TYPE_VIDEO) && duration_count[i]<20 && st->codec.codec_type == CODEC_TYPE_VIDEO)
break; break;
if(st->parser && st->parser->parser->split && !st->codec.extradata)
break;
} }
if (i == ic->nb_streams) { if (i == ic->nb_streams) {
/* NOTE: if the format has no header, then we need to read /* NOTE: if the format has no header, then we need to read
...@@ -1841,6 +1847,15 @@ int av_find_stream_info(AVFormatContext *ic) ...@@ -1841,6 +1847,15 @@ int av_find_stream_info(AVFormatContext *ic)
} }
last_dts[pkt->stream_index]= pkt->dts; last_dts[pkt->stream_index]= pkt->dts;
} }
if(st->parser && st->parser->parser->split && !st->codec.extradata){
int i= st->parser->parser->split(&st->codec, pkt->data, pkt->size);
if(i){
st->codec.extradata_size= i;
st->codec.extradata= av_malloc(st->codec.extradata_size);
memcpy(st->codec.extradata, pkt->data, st->codec.extradata_size);
}
}
/* if still no information, we try to open the codec and to /* if still no information, we try to open the codec and to
decompress the frame. We try to avoid that in most cases as decompress the frame. We try to avoid that in most cases as
it takes longer and uses more memory. For MPEG4, we need to it takes longer and uses more memory. For MPEG4, we need to
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment