gecko-dev/media/libtheora/bug504613.patch
Matthew Gregan 40780c2c4b Bug 504613 - Handle zero-byte first-frame packets in Theora. p=tterribe@vt.edu, r=chris.double
--HG--
extra : rebase_source : d2b18e88ddec3836e30b448f949657206a33f3fa
2009-09-15 17:53:49 +12:00

120 lines
4.5 KiB
Diff

# HG changeset patch
# User Matthew Gregan <kinetik@flim.org>
# Date 1252993590 -43200
# Node ID 2fce745981185aecebad0366b4c2ff45e9f93e95
# Parent 8dbe8de92cb46f64f8ff80d79f38961eb02e9cbd
imported patch bug504613
diff --git a/media/libtheora/lib/dec/decode.c b/media/libtheora/lib/dec/decode.c
--- a/media/libtheora/lib/dec/decode.c
+++ b/media/libtheora/lib/dec/decode.c
@@ -1846,16 +1846,40 @@ int th_decode_ctl(th_dec_ctx *_dec,int _
_dec->stripe_cb.ctx=cb->ctx;
_dec->stripe_cb.stripe_decoded=cb->stripe_decoded;
return 0;
}break;
default:return TH_EIMPL;
}
}
+/*We're decoding an INTER frame, but have no initialized reference
+ buffers (i.e., decoding did not start on a key frame).
+ We initialize them to a solid gray here.*/
+static void oc_dec_init_dummy_frame(th_dec_ctx *_dec){
+ th_info *info;
+ size_t yplane_sz;
+ size_t cplane_sz;
+ int yhstride;
+ int yvstride;
+ int chstride;
+ int cvstride;
+ _dec->state.ref_frame_idx[OC_FRAME_GOLD]=0;
+ _dec->state.ref_frame_idx[OC_FRAME_PREV]=0;
+ _dec->state.ref_frame_idx[OC_FRAME_SELF]=1;
+ info=&_dec->state.info;
+ yhstride=info->frame_width+2*OC_UMV_PADDING;
+ yvstride=info->frame_height+2*OC_UMV_PADDING;
+ chstride=yhstride>>!(info->pixel_fmt&1);
+ cvstride=yvstride>>!(info->pixel_fmt&2);
+ yplane_sz=(size_t)yhstride*yvstride;
+ cplane_sz=(size_t)chstride*cvstride;
+ memset(_dec->state.ref_frame_data,0x80,yplane_sz+2*cplane_sz);
+}
+
int th_decode_packetin(th_dec_ctx *_dec,const ogg_packet *_op,
ogg_int64_t *_granpos){
int ret;
if(_dec==NULL||_op==NULL)return TH_EFAULT;
/*A completely empty packet indicates a dropped frame and is treated exactly
like an inter frame with no coded blocks.
Only proceed if we have a non-empty packet.*/
if(_op->bytes!=0){
@@ -1869,37 +1893,19 @@ int th_decode_packetin(th_dec_ctx *_dec,
theorapackB_readinit(&_dec->opb,_op->packet,_op->bytes);
ret=oc_dec_frame_header_unpack(_dec);
if(ret<0)return ret;
/*Select a free buffer to use for the reconstructed version of this
frame.*/
if(_dec->state.frame_type!=OC_INTRA_FRAME&&
(_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
_dec->state.ref_frame_idx[OC_FRAME_PREV]<0)){
- th_info *info;
- size_t yplane_sz;
- size_t cplane_sz;
- int yhstride;
- int yvstride;
- int chstride;
- int cvstride;
- /*We're decoding an INTER frame, but have no initialized reference
- buffers (i.e., decoding did not start on a key frame).
- We initialize them to a solid gray here.*/
- _dec->state.ref_frame_idx[OC_FRAME_GOLD]=0;
- _dec->state.ref_frame_idx[OC_FRAME_PREV]=0;
- _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi=1;
- info=&_dec->state.info;
- yhstride=info->frame_width+2*OC_UMV_PADDING;
- yvstride=info->frame_height+2*OC_UMV_PADDING;
- chstride=yhstride>>!(info->pixel_fmt&1);
- cvstride=yvstride>>!(info->pixel_fmt&2);
- yplane_sz=(size_t)yhstride*yvstride;
- cplane_sz=(size_t)chstride*cvstride;
- memset(_dec->state.ref_frame_data,0x80,yplane_sz+2*cplane_sz);
+ /*No reference frames yet!*/
+ oc_dec_init_dummy_frame(_dec);
+ refi=_dec->state.ref_frame_idx[OC_FRAME_SELF];
}
else{
for(refi=0;refi==_dec->state.ref_frame_idx[OC_FRAME_GOLD]||
refi==_dec->state.ref_frame_idx[OC_FRAME_PREV];refi++);
_dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
}
if(_dec->state.frame_type==OC_INTRA_FRAME){
oc_dec_mark_all_intra(_dec);
@@ -2036,16 +2042,26 @@ int th_decode_packetin(th_dec_ctx *_dec,
}
#if defined(OC_DUMP_IMAGES)
/*Don't dump images for dropped frames.*/
oc_state_dump_frame(&_dec->state,OC_FRAME_SELF,"dec");
#endif
return 0;
}
else{
+ if(_dec->state.ref_frame_idx[OC_FRAME_GOLD]<0||
+ _dec->state.ref_frame_idx[OC_FRAME_PREV]<0){
+ int refi;
+ /*No reference frames yet!*/
+ oc_dec_init_dummy_frame(_dec);
+ refi=_dec->state.ref_frame_idx[OC_FRAME_PREV];
+ _dec->state.ref_frame_idx[OC_FRAME_SELF]=refi;
+ memcpy(_dec->pp_frame_buf,_dec->state.ref_frame_bufs[refi],
+ sizeof(_dec->pp_frame_buf[0])*3);
+ }
/*Just update the granule position and return.*/
_dec->state.granpos=
(_dec->state.keyframe_num<<_dec->state.info.keyframe_granule_shift)+
(_dec->state.curframe_num-_dec->state.keyframe_num);
_dec->state.curframe_num++;
if(_granpos!=NULL)*_granpos=_dec->state.granpos;
return TH_DUPFRAME;
}