summaryrefslogtreecommitdiff
path: root/src/libffmpeg/libavcodec/h263dec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libffmpeg/libavcodec/h263dec.c')
-rw-r--r--src/libffmpeg/libavcodec/h263dec.c100
1 files changed, 93 insertions, 7 deletions
diff --git a/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c
index 4a1c3dcd5..69e161766 100644
--- a/src/libffmpeg/libavcodec/h263dec.c
+++ b/src/libffmpeg/libavcodec/h263dec.c
@@ -60,7 +60,6 @@ static int h263_decode_init(AVCodecContext *avctx)
switch(avctx->codec->id) {
case CODEC_ID_H263:
s->gob_number = 0;
- s->first_slice_line = 0;
break;
case CODEC_ID_MPEG4:
s->time_increment_bits = 4; /* default value for broken headers */
@@ -126,9 +125,14 @@ static int h263_decode_end(AVCodecContext *avctx)
*/
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 ;)
@@ -191,7 +195,7 @@ static int decode_slice(MpegEncContext *s){
}
/* DCT & quantize */
- clear_blocks(s->block[0]);
+ s->dsp.clear_blocks(s->block[0]);
s->mv_dir = MV_DIR_FORWARD;
s->mv_type = MV_TYPE_16X16;
@@ -252,10 +256,10 @@ static int decode_slice(MpegEncContext *s){
if(bits_left==0 || bits_left>8){
s->padding_bug_score++;
- } else {
+ } else if(bits_left != 1){
int v= show_bits(&s->gb, 8);
v|= 0x7F >> (7-(bits_count&7));
-
+
if(v==0x7F)
s->padding_bug_score--;
else
@@ -300,6 +304,43 @@ static int decode_slice(MpegEncContext *s){
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)
@@ -326,6 +367,42 @@ uint64_t time= rdtsc();
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:
@@ -352,6 +429,9 @@ retry:
}
ret = ff_mpeg4_decode_picture_header(s, &s->gb);
+ if(s->flags& CODEC_FLAG_LOW_DELAY)
+ s->low_delay=1;
+
s->has_b_frames= !s->low_delay;
} else if (s->h263_intel) {
ret = intel_h263_decode_picture_header(s);
@@ -445,10 +525,16 @@ retry:
fprintf(stderr, "header damaged\n");
return -1;
}
+
+ s->avctx->key_frame = (s->pict_type == I_TYPE);
+ s->avctx->pict_type = s->pict_type;
+
/* skip b frames if we dont have reference frames */
if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size);
/* skip b frames if we are in a hurry */
if(s->hurry_up && s->pict_type==B_TYPE) return get_consumed_bytes(s, buf_size);
+ /* skip everything if we are in a hurry>=5 */
+ if(s->hurry_up>=5) return get_consumed_bytes(s, buf_size);
if(s->next_p_frame_damaged){
if(s->pict_type==B_TYPE)
@@ -479,7 +565,7 @@ retry:
decode_slice(s);
s->error_status_table[0]|= VP_START;
- while(s->mb_y<s->mb_height && s->gb.size*8 - get_bits_count(&s->gb)>32){
+ while(s->mb_y<s->mb_height && s->gb.size*8 - get_bits_count(&s->gb)>16){
if(s->msmpeg4_version){
if(s->mb_x!=0 || (s->mb_y%s->slice_height)!=0)
break;
@@ -545,7 +631,7 @@ retry:
num_end_markers--;
}
if(num_end_markers || error){
-// fprintf(stderr, "concealing errors\n");
+ fprintf(stderr, "concealing errors\n");
//printf("type:%d\n", s->pict_type);
ff_error_resilience(s);
}
@@ -625,7 +711,7 @@ AVCodec mpeg4_decoder = {
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 = {