remove CODEC_FLAG_NOT_TRUNCATED & add CODEC_FLAG_TRUNCATED add CODEC_CAP_TRUNCATED add alpha plane to AVPicture remove CODEC_ID_MSMPEG4 remove various unused stuff support "truncated" mpeg4 streams Originally committed as revision 1175 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.5
| @@ -1854,6 +1854,11 @@ void opt_input_file(const char *filename) | |||||
| enc->error_resilience = error_resilience; | enc->error_resilience = error_resilience; | ||||
| enc->error_concealment = error_concealment; | enc->error_concealment = error_concealment; | ||||
| enc->idct_algo= idct_algo; | enc->idct_algo= idct_algo; | ||||
| /* if(enc->codec->capabilities & CODEC_CAP_TRUNCATED) | |||||
| enc->flags|= CODEC_FLAG_TRUNCATED; */ | |||||
| if(/*enc->codec_id==CODEC_ID_MPEG4 || */enc->codec_id==CODEC_ID_MPEG1VIDEO) | |||||
| enc->flags|= CODEC_FLAG_TRUNCATED; | |||||
| if (enc->frame_rate != rfps) { | if (enc->frame_rate != rfps) { | ||||
| fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n", | fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n", | ||||
| i, (float)enc->frame_rate / FRAME_RATE_BASE, | i, (float)enc->frame_rate / FRAME_RATE_BASE, | ||||
| @@ -1224,7 +1224,7 @@ AVOutputFormat asf_oformat = { | |||||
| #else | #else | ||||
| CODEC_ID_MP2, | CODEC_ID_MP2, | ||||
| #endif | #endif | ||||
| CODEC_ID_MSMPEG4, | |||||
| CODEC_ID_MSMPEG4V3, | |||||
| asf_write_header, | asf_write_header, | ||||
| asf_write_packet, | asf_write_packet, | ||||
| asf_write_trailer, | asf_write_trailer, | ||||
| @@ -1241,7 +1241,7 @@ AVOutputFormat asf_stream_oformat = { | |||||
| #else | #else | ||||
| CODEC_ID_MP2, | CODEC_ID_MP2, | ||||
| #endif | #endif | ||||
| CODEC_ID_MSMPEG4, | |||||
| CODEC_ID_MSMPEG4V3, | |||||
| asf_write_stream_header, | asf_write_stream_header, | ||||
| asf_write_packet, | asf_write_packet, | ||||
| asf_write_trailer, | asf_write_trailer, | ||||
| @@ -418,7 +418,7 @@ static AVOutputFormat avi_oformat = { | |||||
| "avi", | "avi", | ||||
| sizeof(AVIContext), | sizeof(AVIContext), | ||||
| CODEC_ID_MP2, | CODEC_ID_MP2, | ||||
| CODEC_ID_MSMPEG4, | |||||
| CODEC_ID_MSMPEG4V3, | |||||
| avi_write_header, | avi_write_header, | ||||
| avi_write_packet, | avi_write_packet, | ||||
| avi_write_trailer, | avi_write_trailer, | ||||
| @@ -536,6 +536,9 @@ int av_find_stream_info(AVFormatContext *ic) | |||||
| st->codec_info_state = CSTATE_FOUND; | st->codec_info_state = CSTATE_FOUND; | ||||
| codec = avcodec_find_decoder(st->codec.codec_id); | codec = avcodec_find_decoder(st->codec.codec_id); | ||||
| if (codec) { | if (codec) { | ||||
| if(codec->capabilities & CODEC_CAP_TRUNCATED) | |||||
| st->codec.flags |= CODEC_FLAG_TRUNCATED; | |||||
| ret = avcodec_open(&st->codec, codec); | ret = avcodec_open(&st->codec, codec); | ||||
| if (ret >= 0) | if (ret >= 0) | ||||
| st->codec_info_state = CSTATE_DECODING; | st->codec_info_state = CSTATE_DECODING; | ||||
| @@ -5,8 +5,8 @@ | |||||
| #define LIBAVCODEC_VERSION_INT 0x000406 | #define LIBAVCODEC_VERSION_INT 0x000406 | ||||
| #define LIBAVCODEC_VERSION "0.4.6" | #define LIBAVCODEC_VERSION "0.4.6" | ||||
| #define LIBAVCODEC_BUILD 4634 | |||||
| #define LIBAVCODEC_BUILD_STR "4634" | |||||
| #define LIBAVCODEC_BUILD 4635 | |||||
| #define LIBAVCODEC_BUILD_STR "4635" | |||||
| enum CodecID { | enum CodecID { | ||||
| CODEC_ID_NONE, | CODEC_ID_NONE, | ||||
| @@ -50,7 +50,6 @@ enum CodecID { | |||||
| CODEC_ID_ADPCM_IMA_WAV, | CODEC_ID_ADPCM_IMA_WAV, | ||||
| CODEC_ID_ADPCM_MS, | CODEC_ID_ADPCM_MS, | ||||
| }; | }; | ||||
| #define CODEC_ID_MSMPEG4 CODEC_ID_MSMPEG4V3 | |||||
| enum CodecType { | enum CodecType { | ||||
| CODEC_TYPE_UNKNOWN = -1, | CODEC_TYPE_UNKNOWN = -1, | ||||
| @@ -80,6 +79,12 @@ enum SampleFormat { | |||||
| /* in bytes */ | /* in bytes */ | ||||
| #define AVCODEC_MAX_AUDIO_FRAME_SIZE 131072 | #define AVCODEC_MAX_AUDIO_FRAME_SIZE 131072 | ||||
| /** | |||||
| * Required number of zero bytes at the end of the input bitstream for decoding. | |||||
| * to avoid overreading (and possibly segfaulting) | |||||
| */ | |||||
| #define FF_INPUT_BUFFER_PADDING_SIZE 8 | |||||
| /* motion estimation type, EPZS by default */ | /* motion estimation type, EPZS by default */ | ||||
| enum Motion_Est_ID { | enum Motion_Est_ID { | ||||
| ME_ZERO = 1, | ME_ZERO = 1, | ||||
| @@ -128,8 +133,8 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, | |||||
| #define CODEC_FLAG_GRAY 0x2000 /* only decode/encode grayscale */ | #define CODEC_FLAG_GRAY 0x2000 /* only decode/encode grayscale */ | ||||
| #define CODEC_FLAG_EMU_EDGE 0x4000/* dont draw edges */ | #define CODEC_FLAG_EMU_EDGE 0x4000/* dont draw edges */ | ||||
| #define CODEC_FLAG_DR1 0x8000 /* direct renderig type 1 (store internal frames in external buffers) */ | #define CODEC_FLAG_DR1 0x8000 /* direct renderig type 1 (store internal frames in external buffers) */ | ||||
| #define CODEC_FLAG_NOT_TRUNCATED 0x00010000 /* input bitstream is not truncated, except before a startcode | |||||
| allows the last part of a frame to be decoded earlier */ | |||||
| #define CODEC_FLAG_TRUNCATED 0x00010000 /* input bitstream might be truncated at a random location instead | |||||
| of only at frame boundaries */ | |||||
| #define CODEC_FLAG_NORMALIZE_AQP 0x00020000 /* normalize adaptive quantization */ | #define CODEC_FLAG_NORMALIZE_AQP 0x00020000 /* normalize adaptive quantization */ | ||||
| #define CODEC_FLAG_INTERLACED_DCT 0x00040000 /* use interlaced dct */ | #define CODEC_FLAG_INTERLACED_DCT 0x00040000 /* use interlaced dct */ | ||||
| #define CODEC_FLAG_LOW_DELAY 0x00080000 /* force low delay / will fail on b frames */ | #define CODEC_FLAG_LOW_DELAY 0x00080000 /* force low delay / will fail on b frames */ | ||||
| @@ -141,6 +146,7 @@ static const int Motion_Est_QTab[] = { ME_ZERO, ME_PHODS, ME_LOG, | |||||
| /* if 'parse_only' field is true, then avcodec_parse_frame() can be | /* if 'parse_only' field is true, then avcodec_parse_frame() can be | ||||
| used */ | used */ | ||||
| #define CODEC_CAP_PARSE_ONLY 0x0004 | #define CODEC_CAP_PARSE_ONLY 0x0004 | ||||
| #define CODEC_CAP_TRUNCATED 0x0008 | |||||
| #define FRAME_RATE_BASE 10000 | #define FRAME_RATE_BASE 10000 | ||||
| @@ -770,10 +776,13 @@ typedef struct AVCodec { | |||||
| struct AVCodec *next; | struct AVCodec *next; | ||||
| } AVCodec; | } AVCodec; | ||||
| /* three components are given, that's all */ | |||||
| /** | |||||
| * four components are given, that's all. | |||||
| * the last component is alpha | |||||
| */ | |||||
| typedef struct AVPicture { | typedef struct AVPicture { | ||||
| UINT8 *data[3]; | |||||
| int linesize[3]; | |||||
| UINT8 *data[4]; | |||||
| int linesize[4]; | |||||
| } AVPicture; | } AVPicture; | ||||
| extern AVCodec ac3_encoder; | extern AVCodec ac3_encoder; | ||||
| @@ -925,13 +934,6 @@ void avcodec_register_all(void); | |||||
| void avcodec_flush_buffers(AVCodecContext *avctx); | void avcodec_flush_buffers(AVCodecContext *avctx); | ||||
| // deprecated / obsolete stuff, WILL be removed | |||||
| #ifndef MBC | |||||
| #define MBC 128 | |||||
| #define MBR 96 | |||||
| #endif | |||||
| #define QP_TYPE int | |||||
| /** | /** | ||||
| * Interface for 0.5.0 version | * Interface for 0.5.0 version | ||||
| * | * | ||||
| @@ -125,9 +125,14 @@ static int h263_decode_end(AVCodecContext *avctx) | |||||
| */ | */ | ||||
| static int get_consumed_bytes(MpegEncContext *s, int buf_size){ | static int get_consumed_bytes(MpegEncContext *s, int buf_size){ | ||||
| int pos= (get_bits_count(&s->gb)+7)>>3; | int pos= (get_bits_count(&s->gb)+7)>>3; | ||||
| if(s->divx_version>=500){ | if(s->divx_version>=500){ | ||||
| //we would have to scan through the whole buf to handle the weird reordering ... | //we would have to scan through the whole buf to handle the weird reordering ... | ||||
| return buf_size; | return buf_size; | ||||
| }else if(s->flags&CODEC_FLAG_TRUNCATED){ | |||||
| pos -= s->parse_context.last_index; | |||||
| if(pos<0) pos=0; // padding is not really read so this might be -1 | |||||
| return pos; | |||||
| }else{ | }else{ | ||||
| if(pos==0) pos=1; //avoid infinite loops (i doubt thats needed but ...) | if(pos==0) pos=1; //avoid infinite loops (i doubt thats needed but ...) | ||||
| if(pos+10>buf_size) pos=buf_size; // oops ;) | if(pos+10>buf_size) pos=buf_size; // oops ;) | ||||
| @@ -299,6 +304,43 @@ static int decode_slice(MpegEncContext *s){ | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| /** | |||||
| * finds the end of the current frame in the bitstream. | |||||
| * @return the position of the first byte of the next frame, or -1 | |||||
| */ | |||||
| static int mpeg4_find_frame_end(MpegEncContext *s, UINT8 *buf, int buf_size){ | |||||
| ParseContext *pc= &s->parse_context; | |||||
| int vop_found, i; | |||||
| uint32_t state; | |||||
| vop_found= pc->frame_start_found; | |||||
| state= pc->state; | |||||
| i=0; | |||||
| if(!vop_found){ | |||||
| for(i=0; i<buf_size; i++){ | |||||
| state= (state<<8) | buf[i]; | |||||
| if(state == 0x1B6){ | |||||
| i++; | |||||
| vop_found=1; | |||||
| break; | |||||
| } | |||||
| } | |||||
| } | |||||
| for(; i<buf_size; i++){ | |||||
| state= (state<<8) | buf[i]; | |||||
| if((state&0xFFFFFF00) == 0x100){ | |||||
| pc->frame_start_found=0; | |||||
| pc->state=-1; | |||||
| return i-3; | |||||
| } | |||||
| } | |||||
| pc->frame_start_found= vop_found; | |||||
| pc->state= state; | |||||
| return -1; | |||||
| } | |||||
| static int h263_decode_frame(AVCodecContext *avctx, | static int h263_decode_frame(AVCodecContext *avctx, | ||||
| void *data, int *data_size, | void *data, int *data_size, | ||||
| UINT8 *buf, int buf_size) | UINT8 *buf, int buf_size) | ||||
| @@ -325,6 +367,42 @@ uint64_t time= rdtsc(); | |||||
| if (buf_size == 0) { | if (buf_size == 0) { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| if(s->flags&CODEC_FLAG_TRUNCATED){ | |||||
| int next; | |||||
| ParseContext *pc= &s->parse_context; | |||||
| pc->last_index= pc->index; | |||||
| if(s->codec_id==CODEC_ID_MPEG4){ | |||||
| next= mpeg4_find_frame_end(s, buf, buf_size); | |||||
| }else{ | |||||
| fprintf(stderr, "this codec doesnt support truncated bitstreams\n"); | |||||
| return -1; | |||||
| } | |||||
| if(next==-1){ | |||||
| if(buf_size + FF_INPUT_BUFFER_PADDING_SIZE + pc->index > pc->buffer_size){ | |||||
| pc->buffer_size= buf_size + pc->index + 10*1024; | |||||
| pc->buffer= realloc(pc->buffer, pc->buffer_size); | |||||
| } | |||||
| memcpy(&pc->buffer[pc->index], buf, buf_size); | |||||
| pc->index += buf_size; | |||||
| return buf_size; | |||||
| } | |||||
| if(pc->index){ | |||||
| if(next + FF_INPUT_BUFFER_PADDING_SIZE + pc->index > pc->buffer_size){ | |||||
| pc->buffer_size= next + pc->index + 10*1024; | |||||
| pc->buffer= realloc(pc->buffer, pc->buffer_size); | |||||
| } | |||||
| memcpy(&pc->buffer[pc->index], buf, next + FF_INPUT_BUFFER_PADDING_SIZE ); | |||||
| pc->index = 0; | |||||
| buf= pc->buffer; | |||||
| buf_size= pc->last_index + next; | |||||
| } | |||||
| } | |||||
| retry: | retry: | ||||
| @@ -627,7 +705,7 @@ AVCodec mpeg4_decoder = { | |||||
| NULL, | NULL, | ||||
| h263_decode_end, | h263_decode_end, | ||||
| h263_decode_frame, | h263_decode_frame, | ||||
| CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, | |||||
| CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED, | |||||
| }; | }; | ||||
| AVCodec h263_decoder = { | AVCodec h263_decoder = { | ||||
| @@ -1876,7 +1876,7 @@ static int mpeg_decode_frame(AVCodecContext *avctx, | |||||
| } else { | } else { | ||||
| memcpy(s->buf_ptr, buf_start, len); | memcpy(s->buf_ptr, buf_start, len); | ||||
| s->buf_ptr += len; | s->buf_ptr += len; | ||||
| if( (s2->flags&CODEC_FLAG_NOT_TRUNCATED) && (!start_code_found) | |||||
| if( (!(s2->flags&CODEC_FLAG_TRUNCATED)) && (!start_code_found) | |||||
| && s->buf_ptr+4<s->buffer+s->buffer_size){ | && s->buf_ptr+4<s->buffer+s->buffer_size){ | ||||
| start_code_found= 1; | start_code_found= 1; | ||||
| code= 0x1FF; | code= 0x1FF; | ||||
| @@ -1971,5 +1971,5 @@ AVCodec mpeg_decoder = { | |||||
| NULL, | NULL, | ||||
| mpeg_decode_end, | mpeg_decode_end, | ||||
| mpeg_decode_frame, | mpeg_decode_frame, | ||||
| CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1, | |||||
| CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED, | |||||
| }; | }; | ||||
| @@ -445,6 +445,8 @@ int MPV_common_init(MpegEncContext *s) | |||||
| s->block= s->blocks[0]; | s->block= s->blocks[0]; | ||||
| s->parse_context.state= -1; | |||||
| s->context_initialized = 1; | s->context_initialized = 1; | ||||
| return 0; | return 0; | ||||
| fail: | fail: | ||||
| @@ -109,6 +109,15 @@ typedef struct ScanTable{ | |||||
| #endif | #endif | ||||
| } ScanTable; | } ScanTable; | ||||
| typedef struct ParseContext{ | |||||
| UINT8 *buffer; | |||||
| int index; | |||||
| int last_index; | |||||
| int buffer_size; | |||||
| int state; | |||||
| int frame_start_found; | |||||
| } ParseContext; | |||||
| typedef struct MpegEncContext { | typedef struct MpegEncContext { | ||||
| struct AVCodecContext *avctx; | struct AVCodecContext *avctx; | ||||
| /* the following parameters must be initialized before encoding */ | /* the following parameters must be initialized before encoding */ | ||||
| @@ -351,6 +360,8 @@ typedef struct MpegEncContext { | |||||
| int mb_num_left; /* number of MBs left in this video packet (for partitioned Slices only)*/ | int mb_num_left; /* number of MBs left in this video packet (for partitioned Slices only)*/ | ||||
| int next_p_frame_damaged; /* set if the next p frame is damaged, to avoid showing trashed b frames */ | int next_p_frame_damaged; /* set if the next p frame is damaged, to avoid showing trashed b frames */ | ||||
| int error_resilience; | int error_resilience; | ||||
| ParseContext parse_context; | |||||
| /* H.263 specific */ | /* H.263 specific */ | ||||
| int gob_number; | int gob_number; | ||||