mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-29 19:02:21 +00:00
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 copy_ts= 0;
|
||||
static int opt_shortest = 0; //
|
||||
static int video_global_header = 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.data= data_buf;
|
||||
opkt.size= data_size;
|
||||
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);
|
||||
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.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);
|
||||
ost->st->codec.frame_number++;
|
||||
ost->frame_number++;
|
||||
av_free_packet(&opkt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3187,8 +3189,12 @@ static void new_video_stream(AVFormatContext *oc)
|
||||
if(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;
|
||||
if(video_global_header&2)
|
||||
video_enc->flags2 |= CODEC_FLAG2_LOCAL_HEADER;
|
||||
|
||||
if (video_stream_copy) {
|
||||
st->stream_copy = 1;
|
||||
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" },
|
||||
{ "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", "" },
|
||||
{ "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" },
|
||||
{ "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_STRICT_GOP 0x00000002 ///< strictly enforce GOP size
|
||||
#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 :
|
||||
* Syntax Arithmetic coding (SAC)
|
||||
@ -2322,6 +2323,7 @@ typedef struct AVCodecParser {
|
||||
uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size);
|
||||
void (*parser_close)(AVCodecParserContext *s);
|
||||
int (*split)(AVCodecContext *avctx, const uint8_t *buf, int buf_size);
|
||||
struct AVCodecParser *next;
|
||||
} AVCodecParser;
|
||||
|
||||
@ -2334,6 +2336,10 @@ int av_parser_parse(AVCodecParserContext *s,
|
||||
uint8_t **poutbuf, int *poutbuf_size,
|
||||
const uint8_t *buf, int buf_size,
|
||||
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);
|
||||
|
||||
extern AVCodecParser mpegvideo_parser;
|
||||
|
@ -142,6 +142,38 @@ int av_parser_parse(AVCodecParserContext *s,
|
||||
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)
|
||||
{
|
||||
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 picture_structure, top_field_first, repeat_first_field, progressive_frame;
|
||||
int horiz_size_ext, vert_size_ext, bit_rate_ext;
|
||||
|
||||
//FIXME replace the crap with get_bits()
|
||||
s->repeat_pict = 0;
|
||||
buf_end = buf + buf_size;
|
||||
while (buf < buf_end) {
|
||||
@ -415,6 +447,20 @@ static int mpegvideo_parse(AVCodecParserContext *s,
|
||||
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)
|
||||
{
|
||||
ParseContext *pc = s->priv_data;
|
||||
@ -493,6 +539,20 @@ static int mpeg4video_parse(AVCodecParserContext *s,
|
||||
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 {
|
||||
@ -768,6 +828,7 @@ AVCodecParser mpegvideo_parser = {
|
||||
NULL,
|
||||
mpegvideo_parse,
|
||||
parse1_close,
|
||||
mpegvideo_split,
|
||||
};
|
||||
|
||||
AVCodecParser mpeg4video_parser = {
|
||||
@ -776,6 +837,7 @@ AVCodecParser mpeg4video_parser = {
|
||||
mpeg4video_parse_init,
|
||||
mpeg4video_parse,
|
||||
parse1_close,
|
||||
mpeg4video_split,
|
||||
};
|
||||
|
||||
AVCodecParser mpegaudio_parser = {
|
||||
|
@ -42,6 +42,7 @@ typedef struct AVPacket {
|
||||
#define PKT_FLAG_KEY 0x0001
|
||||
|
||||
void av_destruct_packet_nofree(AVPacket *pkt);
|
||||
void av_destruct_packet(AVPacket *pkt);
|
||||
|
||||
/* initialize optional fields of a packet */
|
||||
static inline void av_init_packet(AVPacket *pkt)
|
||||
|
@ -165,7 +165,7 @@ AVInputFormat *av_find_input_format(const char *short_name)
|
||||
/**
|
||||
* Default packet destructor
|
||||
*/
|
||||
static void av_destruct_packet(AVPacket *pkt)
|
||||
void av_destruct_packet(AVPacket *pkt)
|
||||
{
|
||||
av_free(pkt->data);
|
||||
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 */
|
||||
st = s->cur_st;
|
||||
if (st) {
|
||||
if (!st->parser) {
|
||||
if (!st->need_parsing || !st->parser) {
|
||||
/* no parsing needed: we just output the packet as is */
|
||||
/* raw data support */
|
||||
*pkt = s->cur_pkt;
|
||||
@ -876,7 +876,7 @@ static int av_read_frame_internal(AVFormatContext *s, AVPacket *pkt)
|
||||
/* return the last frames, if any */
|
||||
for(i = 0; i < s->nb_streams; i++) {
|
||||
st = s->streams[i];
|
||||
if (st->parser) {
|
||||
if (st->parser && st->need_parsing) {
|
||||
av_parser_parse(st->parser, &st->codec,
|
||||
&pkt->data, &pkt->size,
|
||||
NULL, 0,
|
||||
@ -1742,6 +1742,10 @@ int av_find_stream_info(AVFormatContext *ic)
|
||||
if(!st->codec.time_base.num)
|
||||
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++){
|
||||
@ -1762,6 +1766,8 @@ int av_find_stream_info(AVFormatContext *ic)
|
||||
if( st->codec.time_base.den >= 1000LL*st->codec.time_base.num
|
||||
&& duration_count[i]<20 && st->codec.codec_type == CODEC_TYPE_VIDEO)
|
||||
break;
|
||||
if(st->parser && st->parser->parser->split && !st->codec.extradata)
|
||||
break;
|
||||
}
|
||||
if (i == ic->nb_streams) {
|
||||
/* 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;
|
||||
}
|
||||
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
|
||||
decompress the frame. We try to avoid that in most cases as
|
||||
it takes longer and uses more memory. For MPEG4, we need to
|
||||
|
Loading…
Reference in New Issue
Block a user