support changing in bitstream global headers into extradata style and back
Originally committed as revision 4395 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
718b27a7d0
commit
90ad92b39d
13
ffmpeg.c
13
ffmpeg.c
@ -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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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[] = {
|
|||||||
{ "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*)©_ts}, "copy timestamps" },
|
{ "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_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;
|
|||||||
#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 {
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 = {
|
|||||||
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 = {
|
|||||||
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 {
|
|||||||
#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)
|
|||||||
/**
|
/**
|
||||||
* 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)
|
|||||||
/* 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)
|
|||||||
/* 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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user