enc->error_resilience = error_resilience;
enc->error_concealment = error_concealment;
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) {
fprintf(stderr,"\nSeems that stream %d comes from film source: %2.2f->%2.2f\n",
i, (float)enc->frame_rate / FRAME_RATE_BASE,
#else
CODEC_ID_MP2,
#endif
- CODEC_ID_MSMPEG4,
+ CODEC_ID_MSMPEG4V3,
asf_write_header,
asf_write_packet,
asf_write_trailer,
#else
CODEC_ID_MP2,
#endif
- CODEC_ID_MSMPEG4,
+ CODEC_ID_MSMPEG4V3,
asf_write_stream_header,
asf_write_packet,
asf_write_trailer,
"avi",
sizeof(AVIContext),
CODEC_ID_MP2,
- CODEC_ID_MSMPEG4,
+ CODEC_ID_MSMPEG4V3,
avi_write_header,
avi_write_packet,
avi_write_trailer,
st->codec_info_state = CSTATE_FOUND;
codec = avcodec_find_decoder(st->codec.codec_id);
if (codec) {
+ if(codec->capabilities & CODEC_CAP_TRUNCATED)
+ st->codec.flags |= CODEC_FLAG_TRUNCATED;
+
ret = avcodec_open(&st->codec, codec);
if (ret >= 0)
st->codec_info_state = CSTATE_DECODING;
#define LIBAVCODEC_VERSION_INT 0x000406
#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 {
CODEC_ID_NONE,
CODEC_ID_ADPCM_IMA_WAV,
CODEC_ID_ADPCM_MS,
};
-#define CODEC_ID_MSMPEG4 CODEC_ID_MSMPEG4V3
enum CodecType {
CODEC_TYPE_UNKNOWN = -1,
/* in bytes */
#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 */
enum Motion_Est_ID {
ME_ZERO = 1,
#define CODEC_FLAG_GRAY 0x2000 /* only decode/encode grayscale */
#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_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_INTERLACED_DCT 0x00040000 /* use interlaced dct */
#define CODEC_FLAG_LOW_DELAY 0x00080000 /* force low delay / will fail on b frames */
/* if 'parse_only' field is true, then avcodec_parse_frame() can be
used */
#define CODEC_CAP_PARSE_ONLY 0x0004
+#define CODEC_CAP_TRUNCATED 0x0008
#define FRAME_RATE_BASE 10000
struct AVCodec *next;
} AVCodec;
-/* three components are given, that's all */
+/**
+ * four components are given, that's all.
+ * the last component is alpha
+ */
typedef struct AVPicture {
- UINT8 *data[3];
- int linesize[3];
+ UINT8 *data[4];
+ int linesize[4];
} AVPicture;
extern AVCodec ac3_encoder;
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
*
*/
static int get_consumed_bytes(MpegEncContext *s, int buf_size){
int pos= (get_bits_count(&s->gb)+7)>>3;
+
if(s->divx_version>=500){
//we would have to scan through the whole buf to handle the weird reordering ...
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{
if(pos==0) pos=1; //avoid infinite loops (i doubt thats needed but ...)
if(pos+10>buf_size) pos=buf_size; // oops ;)
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,
void *data, int *data_size,
UINT8 *buf, int buf_size)
if (buf_size == 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:
NULL,
h263_decode_end,
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 = {
} else {
memcpy(s->buf_ptr, buf_start, 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){
start_code_found= 1;
code= 0x1FF;
NULL,
mpeg_decode_end,
mpeg_decode_frame,
- CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1,
+ CODEC_CAP_DRAW_HORIZ_BAND | CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED,
};
s->block= s->blocks[0];
+ s->parse_context.state= -1;
+
s->context_initialized = 1;
return 0;
fail:
#endif
} ScanTable;
+typedef struct ParseContext{
+ UINT8 *buffer;
+ int index;
+ int last_index;
+ int buffer_size;
+ int state;
+ int frame_start_found;
+} ParseContext;
+
typedef struct MpegEncContext {
struct AVCodecContext *avctx;
/* the following parameters must be initialized before encoding */
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 error_resilience;
+
+ ParseContext parse_context;
/* H.263 specific */
int gob_number;