[Ffmpeg-devel] [PATCH] Chinese AVS video decoder
Måns Rullgård
mru
Sun Jul 2 03:27:42 CEST 2006
Michael Niedermayer <michaelni at gmx.at> writes:
> Hi
>
> On Sun, Jul 02, 2006 at 12:36:26AM +0100, M?ns Rullg?rd wrote:
>> Some comments based on discussions on IRC and other observations.
>>
>> > +typedef struct {
>> > + int16_t x;
>> > + int16_t y;
>> > + int16_t dist;
>> > + int16_t ref;
>> > +} vector_t;
>>
>> If this is marked with __attribute__((align(8))) gcc will be able to
>> read/write the entire thing with one instruction on 64-bit machines.
>
> yes but to avoid breaking non gcc __attribute__ cant be added directly
> maybe DECLARE_ALIGNED_8() could be used ...
Hmm, it can with gcc at least, although it looks a bit odd. You'll
have to choose from
DECLARE_ALIGNED_8(typedef, struct) {
int16_t x;
int16_t y;
int16_t dist;
int16_t ref;
} vector_t;
or
typedef struct {
int16_t x;
int16_t y;
int16_t dist;
int16_t ref;
} DECLARE_ALIGNED_8(vector_t,);
of variants thereof.
>> > +static void intra_pred_vert(uint8_t *d,uint8_t *top,uint8_t *left,int stride) {
>> > + int y;
>> > + uint64_t a = *((uint64_t *)(&top[1]));
>> > + for(y=0;y<8;y++) {
>> > + *((uint64_t *)(d+y*stride)) = a;
>> > + }
>> > +}
>> > +
>> > +static void intra_pred_horiz(uint8_t *d,uint8_t *top,uint8_t *left,int stride) {
>> > + int y;
>> > + uint64_t a;
>> > + for(y=0;y<8;y++) {
>> > + a = left[y+1] * 0x0101010101010101ULL;
>> > + *((uint64_t *)(d+y*stride)) = a;
>> > + }
>> > +}
>> > +
>> > +static void intra_pred_dc_128(uint8_t *d,uint8_t *top,uint8_t *left,int stride) {
>> > + int y;
>> > + uint64_t a = 0x8080808080808080ULL;
>> > + for(y=0;y<8;y++)
>> > + *((uint64_t *)(d+y*stride)) = a;
>> > +}
>>
>> More alignment trouble.
>
> hmm, where is the problem in the 2nd and 3rd function you quote? without
> looking at the original code id say stride and d must be aigned to 8
Alright, let's see. The function would be called from this loop:
for(block=0;block<4;block++) {
d = h->cy + h->luma_scan[block];
load_intra_pred_luma(h, top, left, block);
h->intra_pred_l[(int)h->pred_mode_Y[scan3x3[block]]]
(d, top, left, h->l_stride);
if(h->cbp & (1<<block))
decode_residual_block(h,gb,intra_2dvlc,1,h->qp,d,h->l_stride);
}
or from one of these lines:
h->intra_pred_c[pred_mode_uv](h->cu, top, left, h->c_stride);
h->intra_pred_c[pred_mode_uv](h->cv, top, left, h->c_stride);
h->cy, h->cu, h->cv are all set from h->picture.data[x], which I
suppose are aligned, offset by multiples of 8. h->luma_scan[x] are
also all multiples of 8 so I guess it's safe after all.
I was only doing a quick scan for suspicious-looking things, and those
kinds of casts certainly need some extra care.
I a nasty one on the first pass:
typedef struct {
MpegEncContext s;
Picture picture; //currently decoded frame
Picture DPB[2]; //reference frames
[...]
} AVSContext;
Those should be AVFrame, or else the code fragments below are not good
at all. In fact, I'm surprised it's not causing any serious trouble.
if(h->picture.data[0])
s->avctx->release_buffer(s->avctx, (AVFrame *)&h->picture);
s->avctx->get_buffer(s->avctx, (AVFrame *)&h->picture);
[...]
if(h->pic_type != FF_B_TYPE) {
if(h->DPB[1].data[0])
s->avctx->release_buffer(s->avctx, (AVFrame *)&h->DPB[1]);
memcpy(&h->DPB[1], &h->DPB[0], sizeof(Picture));
memcpy(&h->DPB[0], &h->picture, sizeof(Picture));
memset(&h->picture,0,sizeof(Picture));
}
[...]
if (buf_size == 0) {
if(!s->low_delay && h->DPB[0].data[0]) {
*data_size = sizeof(AVPicture);
*picture = *(AVFrame *) &h->DPB[0];
}
return 0;
}
[...]
if(!h->got_keyframe) {
if(h->DPB[0].data[0])
avctx->release_buffer(avctx, (AVFrame *)&h->DPB[0]);
if(h->DPB[1].data[0])
avctx->release_buffer(avctx, (AVFrame *)&h->DPB[1]);
h->got_keyframe = 1;
}
[...]
if(h->pic_type != FF_B_TYPE) {
if(h->DPB[1].data[0]) {
*picture = *(AVFrame *) &h->DPB[1];
} else {
*data_size = 0;
}
} else
*picture = *(AVFrame *) &h->picture;
This is a good example of why blindly adding a cast to silence a
compiler warning is a very, very bad idea.
--
M?ns Rullg?rd
mru at inprovide.com
More information about the ffmpeg-devel
mailing list