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.c297
1 files changed, 247 insertions, 50 deletions
diff --git a/src/libffmpeg/libavcodec/h263dec.c b/src/libffmpeg/libavcodec/h263dec.c
index e909ac56e..3c90a1e47 100644
--- a/src/libffmpeg/libavcodec/h263dec.c
+++ b/src/libffmpeg/libavcodec/h263dec.c
@@ -1,53 +1,60 @@
/*
* H263 decoder
- * Copyright (c) 2001 Gerard Lantau.
+ * Copyright (c) 2001 Fabrice Bellard.
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
+ * This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "config.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "dsputil.h"
#include "avcodec.h"
+#include "dsputil.h"
#include "mpegvideo.h"
-#include "xine-utils/xineutils.h"
//#define DEBUG
+//#define PRINT_FRAME_TIME
+#ifdef PRINT_FRAME_TIME
+static inline long long rdtsc()
+{
+ long long l;
+ asm volatile( "rdtsc\n\t"
+ : "=A" (l)
+ );
+// printf("%d\n", int(l/1000));
+ return l;
+}
+#endif
static int h263_decode_init(AVCodecContext *avctx)
{
MpegEncContext *s = avctx->priv_data;
- int i;
s->avctx = avctx;
s->out_format = FMT_H263;
s->width = avctx->width;
s->height = avctx->height;
+ s->workaround_bugs= avctx->workaround_bugs;
/* select sub codec */
switch(avctx->codec->id) {
case CODEC_ID_H263:
s->gob_number = 0;
- s->first_gob_line = 0;
+ s->first_slice_line = 0;
break;
case CODEC_ID_MPEG4:
s->time_increment_bits = 4; /* default value for broken headers */
s->h263_pred = 1;
- s->has_b_frames = 1;
+ s->has_b_frames = 1; //default, might be overriden in the vol header during header parsing
break;
case CODEC_ID_MSMPEG4V1:
s->h263_msmpeg4 = 1;
@@ -64,23 +71,25 @@ static int h263_decode_init(AVCodecContext *avctx)
s->h263_pred = 1;
s->msmpeg4_version=3;
break;
+ case CODEC_ID_WMV1:
+ s->h263_msmpeg4 = 1;
+ s->h263_pred = 1;
+ s->msmpeg4_version=4;
+ break;
case CODEC_ID_H263I:
s->h263_intel = 1;
break;
default:
return -1;
}
-
+ s->codec_id= avctx->codec->id;
+ avctx->mbskip_table= s->mbskip_table;
+
/* for h263, we allocate the images after having read the header */
if (avctx->codec->id != CODEC_ID_H263 && avctx->codec->id != CODEC_ID_MPEG4)
if (MPV_common_init(s) < 0)
return -1;
- /* XXX: suppress this matrix init, only needed because using mpeg1
- dequantize in mmx case */
- for(i=0;i<64;i++)
- s->non_intra_matrix[i] = default_non_intra_matrix[i];
-
if (s->h263_msmpeg4)
msmpeg4_decode_init_vlc(s);
else
@@ -104,25 +113,37 @@ static int h263_decode_frame(AVCodecContext *avctx,
MpegEncContext *s = avctx->priv_data;
int ret;
AVPicture *pict = data;
-
+#ifdef PRINT_FRAME_TIME
+uint64_t time= rdtsc();
+#endif
#ifdef DEBUG
printf("*****frame %d size=%d\n", avctx->frame_number, buf_size);
printf("bytes=%x %x %x %x\n", buf[0], buf[1], buf[2], buf[3]);
#endif
-
+
+ s->hurry_up= avctx->hurry_up;
+ s->error_resilience= avctx->error_resilience;
+ s->workaround_bugs= avctx->workaround_bugs;
+ s->flags= avctx->flags;
+
/* no supplementary picture */
if (buf_size == 0) {
*data_size = 0;
return 0;
}
- init_get_bits(&s->gb, buf, buf_size);
+ if(s->bitstream_buffer_size && buf_size<20){ //divx 5.01+ frame reorder
+ init_get_bits(&s->gb, s->bitstream_buffer, s->bitstream_buffer_size);
+ }else
+ init_get_bits(&s->gb, buf, buf_size);
+ s->bitstream_buffer_size=0;
/* let's go :-) */
if (s->h263_msmpeg4) {
ret = msmpeg4_decode_picture_header(s);
} else if (s->h263_pred) {
ret = mpeg4_decode_picture_header(s);
+ s->has_b_frames= !s->low_delay;
} else if (s->h263_intel) {
ret = intel_h263_decode_picture_header(s);
} else {
@@ -146,8 +167,21 @@ static int h263_decode_frame(AVCodecContext *avctx,
return -1;
}
+ if(ret==FRAME_SKIPED) return 0;
+ /* skip if the header was thrashed */
if (ret < 0)
return -1;
+ /* skip b frames if we dont have reference frames */
+ if(s->num_available_buffers<2 && s->pict_type==B_TYPE) return 0;
+ /* skip b frames if we are in a hurry */
+ if(s->hurry_up && s->pict_type==B_TYPE) return 0;
+
+ if(s->next_p_frame_damaged){
+ if(s->pict_type==B_TYPE)
+ return 0;
+ else
+ s->next_p_frame_damaged=0;
+ }
MPV_frame_start(s);
@@ -155,6 +189,12 @@ static int h263_decode_frame(AVCodecContext *avctx,
printf("qscale=%d\n", s->qscale);
#endif
+ /* init resync/ error resilience specific variables */
+ s->next_resync_qscale= s->qscale;
+ s->next_resync_gb= s->gb;
+ if(s->resync_marker) s->mb_num_left= 0;
+ else s->mb_num_left= s->mb_num;
+
/* decode each macroblock */
s->block_wrap[0]=
s->block_wrap[1]=
@@ -167,7 +207,13 @@ static int h263_decode_frame(AVCodecContext *avctx,
/* FIXME: In the future H.263+ will have intra prediction */
/* and we are gonna need another way to detect MPEG4 */
if (s->mb_y && !s->h263_pred) {
- s->first_gob_line = h263_decode_gob_header(s);
+ s->first_slice_line = h263_decode_gob_header(s);
+ }
+
+ if(s->msmpeg4_version==1){
+ s->last_dc[0]=
+ s->last_dc[1]=
+ s->last_dc[2]= 128;
}
s->block_index[0]= s->block_wrap[0]*(s->mb_y*2 + 1) - 1;
@@ -186,35 +232,95 @@ static int h263_decode_frame(AVCodecContext *avctx,
#ifdef DEBUG
printf("**mb x=%d y=%d\n", s->mb_x, s->mb_y);
#endif
+
+ if(s->resync_marker){
+ if(s->mb_num_left<=0){
+ /* except the first block */
+ if(s->mb_x!=0 || s->mb_y!=0){
+ /* did we miss the next resync marker without noticing an error yet */
+ if(((get_bits_count(&s->gb)+8)&(~7)) != s->next_resync_pos && s->decoding_error==0){
+ fprintf(stderr, "slice end missmatch x:%d y:%d %d %d\n",
+ s->mb_x, s->mb_y, get_bits_count(&s->gb), s->next_resync_pos);
+ ff_conceal_past_errors(s, 1);
+ }
+ }
+ s->qscale= s->next_resync_qscale;
+ s->gb= s->next_resync_gb;
+ s->resync_mb_x= s->mb_x; //we know that the marker is here cuz mb_num_left was the distance to it
+ s->resync_mb_y= s->mb_y;
+ s->first_slice_line=1;
+
+ if(s->codec_id==CODEC_ID_MPEG4){
+ ff_mpeg4_clean_buffers(s);
+ ff_mpeg4_resync(s);
+ }
+ }
+
+ if( s->resync_mb_x==s->mb_x
+ && s->resync_mb_y==s->mb_y && s->decoding_error!=0){
+ fprintf(stderr, "resynced at %d %d\n", s->mb_x, s->mb_y);
+ s->decoding_error= 0;
+ }
+ }
+
//fprintf(stderr,"\nFrame: %d\tMB: %d",avctx->frame_number, (s->mb_y * s->mb_width) + s->mb_x);
/* DCT & quantize */
- if (s->h263_msmpeg4) {
- msmpeg4_dc_scale(s);
- } else if (s->h263_pred) {
- h263_dc_scale(s);
+ if (s->h263_pred && !(s->msmpeg4_version==1 || s->msmpeg4_version==2)) {
+ /* old ffmpeg encoded msmpeg4v3 workaround */
+ if(s->workaround_bugs==1 && s->msmpeg4_version==3)
+ ff_old_msmpeg4_dc_scale(s);
+ else
+ h263_dc_scale(s);
} else {
/* default quantization values */
s->y_dc_scale = 8;
s->c_dc_scale = 8;
}
- clear_blocks(s->block[0]);
+
+ if(s->decoding_error!=DECODING_DESYNC){
+ int last_error= s->decoding_error;
+ clear_blocks(s->block[0]);
- s->mv_dir = MV_DIR_FORWARD;
- s->mv_type = MV_TYPE_16X16;
- if (s->h263_msmpeg4) {
- if (msmpeg4_decode_mb(s, s->block) < 0) {
- fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
- return -1;
- }
- } else {
- if (h263_decode_mb(s, s->block) < 0) {
- fprintf(stderr,"\nError at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
- return -1;
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ if (s->h263_msmpeg4) {
+ if (msmpeg4_decode_mb(s, s->block) < 0) {
+ fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
+ s->decoding_error=DECODING_DESYNC;
+ }
+ } else {
+ if (h263_decode_mb(s, s->block) < 0) {
+ fprintf(stderr,"Error at MB: %d\n", (s->mb_y * s->mb_width) + s->mb_x);
+ s->decoding_error=DECODING_DESYNC;
+ }
+ }
+
+ if(s->decoding_error!=last_error){
+ ff_conceal_past_errors(s, 0);
}
}
+
+ /* conceal errors */
+ if( s->decoding_error==DECODING_DESYNC
+ || (s->decoding_error==DECODING_ACDC_LOST && s->mb_intra)){
+ s->mv_dir = MV_DIR_FORWARD;
+ s->mv_type = MV_TYPE_16X16;
+ s->mb_skiped=0;
+ s->mb_intra=0;
+ s->mv[0][0][0]=0; //FIXME this is not optimal
+ s->mv[0][0][1]=0;
+ clear_blocks(s->block[0]);
+ }else if(s->decoding_error && !s->mb_intra){
+ clear_blocks(s->block[0]);
+ }
+ //FIXME remove AC for intra
+
MPV_decode_mb(s, s->block);
+
+ s->mb_num_left--;
}
- if (avctx->draw_horiz_band) {
+ if ( avctx->draw_horiz_band
+ && (s->num_available_buffers>=1 || (!s->has_b_frames)) ) {
UINT8 *src_ptr[3];
int y, h, offset;
y = s->mb_y * 16;
@@ -236,11 +342,84 @@ static int h263_decode_frame(AVCodecContext *avctx,
}
}
- if (s->h263_msmpeg4 && s->pict_type==I_TYPE)
+ if (s->h263_msmpeg4 && s->msmpeg4_version<4 && s->pict_type==I_TYPE)
if(msmpeg4_decode_ext_header(s, buf_size) < 0) return -1;
+
+ /* divx 5.01+ bistream reorder stuff */
+ if(s->codec_id==CODEC_ID_MPEG4 && s->bitstream_buffer_size==0){
+ int current_pos= get_bits_count(&s->gb)>>3;
+ if( buf_size - current_pos > 5
+ && buf_size - current_pos < BITSTREAM_BUFFER_SIZE){
+ int i;
+ int startcode_found=0;
+ for(i=current_pos; i<buf_size; i++){
+ if(buf[i]==0 && buf[i+1]==0 && buf[i+2]==1 && buf[i+3]==0xB6){
+ startcode_found=1;
+ break;
+ }
+ }
+ if(startcode_found){
+ memcpy(s->bitstream_buffer, buf + current_pos, buf_size - current_pos);
+ s->bitstream_buffer_size= buf_size - current_pos;
+ }
+ }
+ }
+
+ if(s->bitstream_buffer_size==0 && s->error_resilience>0){
+ int left= s->gb.size*8 - get_bits_count(&s->gb);
+ int max_extra=8;
+
+ if(s->codec_id==CODEC_ID_MPEG4) max_extra+=32;
+
+ if(left>max_extra){
+ fprintf(stderr, "discarding %d junk bits at end, next would be %X\n", left, show_bits(&s->gb, 24));
+ if(s->decoding_error==0)
+ ff_conceal_past_errors(s, 1);
+ }
+ if(left<0){
+ fprintf(stderr, "overreading %d bits\n", -left);
+ if(s->decoding_error==0)
+ ff_conceal_past_errors(s, 1);
+ }
+ }
+
MPV_frame_end(s);
-
+#if 0 //dirty show MVs, we should export the MV tables and write a filter to show them
+{
+ int mb_y;
+ s->has_b_frames=1;
+ for(mb_y=0; mb_y<s->mb_height; mb_y++){
+ int mb_x;
+ int y= mb_y*16 + 8;
+ for(mb_x=0; mb_x<s->mb_width; mb_x++){
+ int x= mb_x*16 + 8;
+ uint8_t *ptr= s->last_picture[0];
+ int xy= 1 + mb_x*2 + (mb_y*2 + 1)*(s->mb_width*2 + 2);
+ int mx= (s->motion_val[xy][0]>>1) + x;
+ int my= (s->motion_val[xy][1]>>1) + y;
+ int i;
+ int max;
+
+ if(mx<0) mx=0;
+ if(my<0) my=0;
+ if(mx>=s->width) mx= s->width -1;
+ if(my>=s->height) my= s->height-1;
+ max= ABS(mx-x);
+ if(ABS(my-y) > max) max= ABS(my-y);
+ /* the ugliest linedrawing routine ... */
+ for(i=0; i<max; i++){
+ int x1= x + (mx-x)*i/max;
+ int y1= y + (my-y)*i/max;
+ ptr[y1*s->linesize + x1]+=100;
+ }
+ ptr[y*s->linesize + x]+=100;
+ s->mbskip_table[mb_x + mb_y*s->mb_width]=0;
+ }
+ }
+
+}
+#endif
if(s->pict_type==B_TYPE || (!s->has_b_frames)){
pict->data[0] = s->current_picture[0];
pict->data[1] = s->current_picture[1];
@@ -260,7 +439,13 @@ static int h263_decode_frame(AVCodecContext *avctx,
/* we substract 1 because it is added on utils.c */
avctx->frame_number = s->picture_number - 1;
- *data_size = sizeof(AVPicture);
+ /* dont output the last pic after seeking
+ note we allready added +1 for the current pix in MPV_frame_end(s) */
+ if(s->num_available_buffers>=2 || (!s->has_b_frames))
+ *data_size = sizeof(AVPicture);
+#ifdef PRINT_FRAME_TIME
+printf("%Ld\n", rdtsc()-time);
+#endif
return buf_size;
}
@@ -324,6 +509,18 @@ AVCodec msmpeg4v3_decoder = {
CODEC_CAP_DRAW_HORIZ_BAND,
};
+AVCodec wmv1_decoder = {
+ "wmv1",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV1,
+ sizeof(MpegEncContext),
+ h263_decode_init,
+ NULL,
+ h263_decode_end,
+ h263_decode_frame,
+ CODEC_CAP_DRAW_HORIZ_BAND,
+};
+
AVCodec h263i_decoder = {
"h263i",
CODEC_TYPE_VIDEO,