Hey Christian,

On 12/20/2011 02:16 PM, Christian König wrote:
> On 20.12.2011 12:43, Maarten Lankhorst wrote:
>> And add more sanity checks to stream. This shouldn't break things beyond 
>> those that aren't broken already.
>>
>> Signed-off-by: Maarten Lankhorst<m.b.lankho...@gmail.com>
>>
>> ---
>> And yes Andy, I mean that I haven't found a good video yet to fix the 
>> playback parts that are still broken..
> Why do you want to change that anyway?
>
> The search for start codes was especially split out of the VLC stuff, because 
> start codes start are byte aligned anyway and it doesn't make much sense to 
> search for them using the slower peekbits & fillbits functions.
Since 4 bytes are loaded at a time and bit aligning is fast enough, it's not 
that much slower, the reason I want this is to be able to add support for when 
the array size is > 1, currently and even with that patch its not handled, but 
if a slice is split between multiple buffers you can at least pick up where you 
left.. for example with mplayer I have observed that the start code 
0x00,0x00,0x01 and the actual value are in separate buffers for some codecs, 
and for wmv the following is said:

 * Some VC-1 advanced profile streams do not contain slice start codes; again,
 * the container format must indicate where picture data begins and ends. In
 * this case, pictures are assumed to be progressive and to contain a single
 * slice. It is highly recommended that applications detect this condition,
 * and add the missing start codes to the bitstream passed to VDPAU. However,
 * VDPAU implementations must allow bitstreams with missing start codes, and
 * act as if a 0x0000010D (frame) start code had been present.

Since mplayer can chop up the start code and the 0x0d, you'd need a parser to 
handle this.
I planned on using vlc to detect the lack of start code.

> Se below for some further comments.
>>   src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c |   56 
>> +++++++++++-------------
>>   src/gallium/auxiliary/vl/vl_vlc.h              |   33 +++++++++-----
>>   2 files changed, 47 insertions(+), 42 deletions(-)
>>
>> diff --git a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c 
>> b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
>> index 936cf2c..62d08d7 100644
>> --- a/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
>> +++ b/src/gallium/auxiliary/vl/vl_mpeg12_bitstream.c
>> @@ -787,7 +787,7 @@ entry:
>>   }
>>
>>   static INLINE bool
>> -decode_slice(struct vl_mpg12_bs *bs)
>> +decode_slice(struct vl_mpg12_bs *bs, unsigned code)
>>   {
>>      struct pipe_mpeg12_macroblock mb;
>>      short dct_blocks[64*6];
>> @@ -796,24 +796,29 @@ decode_slice(struct vl_mpg12_bs *bs)
>>
>>      memset(&mb, 0, sizeof(mb));
>>      mb.base.codec = PIPE_VIDEO_CODEC_MPEG12;
>> -   mb.y = vl_vlc_get_uimsbf(&bs->vlc, 8) - 1;
>> +   mb.y = code - 1;
>>      mb.blocks = dct_blocks;
>>
>>      reset_predictor(bs);
>> +   vl_vlc_fillbits(&bs->vlc);
>>      dct_scale = 
>> quant_scale[bs->desc.q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)];
>>
>> -   if (vl_vlc_get_uimsbf(&bs->vlc, 1))
>> +   if (vl_vlc_get_uimsbf(&bs->vlc, 1)) {
>> +      vl_vlc_fillbits(&bs->vlc);
>>         while (vl_vlc_get_uimsbf(&bs->vlc, 9)&  1)
>>            vl_vlc_fillbits(&bs->vlc);
>> +   }
>>
>>      vl_vlc_fillbits(&bs->vlc);
>> +   assert(vl_vlc_bits_left(&bs->vlc)>  23&&  vl_vlc_peekbits(&bs->vlc, 23));
>>      do {
>>         int inc = 0;
>>
>> -      while (vl_vlc_peekbits(&bs->vlc, 11) == 15) {
>> -         vl_vlc_eatbits(&bs->vlc, 11);
>> -         vl_vlc_fillbits(&bs->vlc);
>> -      }
>> +      if (bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1)
>> +         while (vl_vlc_peekbits(&bs->vlc, 11) == 15) {
>> +            vl_vlc_eatbits(&bs->vlc, 11);
>> +            vl_vlc_fillbits(&bs->vlc);
>> +         }
>>
>>         while (vl_vlc_peekbits(&bs->vlc, 11) == 8) {
>>            vl_vlc_eatbits(&bs->vlc, 11);
>> @@ -959,32 +964,23 @@ void
>>   vl_mpg12_bs_decode(struct vl_mpg12_bs *bs, unsigned num_bytes, const 
>> uint8_t *buffer)
>>   {
>>      assert(bs);
>> -   assert(buffer&&  num_bytes);
>> -
>> -   while(num_bytes>  2) {
>> -      if (buffer[0] == 0x00&&  buffer[1] == 0x00&&  buffer[2] == 0x01&&
>> -    buffer[3]>= 0x01&&  buffer[3]<  0xAF) {
>> -         unsigned consumed;
>>
>> -         buffer += 3;
>> -         num_bytes -= 3;
>> +   vl_vlc_init(&bs->vlc, 1, num_bytes, (void const * const 
>> *)&buffer,&num_bytes);
>>
>> -         vl_vlc_init(&bs->vlc, buffer, num_bytes);
>> -
>> -         if (!decode_slice(bs))
>> +   while (vl_vlc_bits_left(&bs->vlc)>= 32) {
>> +      vl_vlc_fillbits(&bs->vlc);
>> +      if (vl_vlc_peekbits(&bs->vlc, 24) == 0x000001) {
>> +         unsigned code;
>> +         vl_vlc_eatbits(&bs->vlc, 24);
>> +         code = vl_vlc_get_uimsbf(&bs->vlc, 8);
>> +         if (!code || code>  0xaf)
>> +            continue;
>> +         if (!decode_slice(bs, code))
>>               return;
>> -
>> -         consumed = num_bytes - vl_vlc_bits_left(&bs->vlc) / 8;
>> -
>> -         /* crap, this is a bug we have consumed more bytes than left in 
>> the buffer */
>> -         assert(consumed<= num_bytes);
>> -
>> -         num_bytes -= consumed;
>> -         buffer += consumed;
>> -
>> +         vl_vlc_bitalign(&bs->vlc);
>>         } else {
>> -         ++buffer;
>> -         --num_bytes;
>> +         vl_vlc_eatbits(&bs->vlc, 8);
>> +         continue;
>>         }
>>      }
>>   }
>> diff --git a/src/gallium/auxiliary/vl/vl_vlc.h 
>> b/src/gallium/auxiliary/vl/vl_vlc.h
>> index dc4faed..a4ded70 100644
>> --- a/src/gallium/auxiliary/vl/vl_vlc.h
>> +++ b/src/gallium/auxiliary/vl/vl_vlc.h
>> @@ -38,7 +38,7 @@
>>   struct vl_vlc
>>   {
>>      uint64_t buffer;
>> -   unsigned valid_bits;
>> +   uint32_t valid_bits;
>>      uint32_t *data;
>>      uint32_t *end;
>>   };
>> @@ -74,11 +74,9 @@ vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned 
>> dst_size, const struct vl_v
>>   static INLINE void
>>   vl_vlc_fillbits(struct vl_vlc *vlc)
>>   {
>> -   if (vlc->valid_bits<  32) {
>> +   if (vlc->valid_bits<  32&&  vlc->data<  vlc->end) {
>>         uint32_t value = *vlc->data;
> The correct sollution would be to let fillbits return a boolean signaling 
> that the buffer(s) are depleted.
Maybe, I want to start filling from the next stream if this is the case.

>>
>> -      //assert(vlc->data<= vlc->end);
>> -
>>   #ifndef PIPE_ARCH_BIG_ENDIAN
>>         value = util_bswap32(value);
>>   #endif
>> @@ -90,10 +88,14 @@ vl_vlc_fillbits(struct vl_vlc *vlc)
>>   }
>>
>>   static INLINE void
>> -vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, unsigned len)
>> +vl_vlc_init(struct vl_vlc *vlc,
>> +            const unsigned array_size, unsigned total_len,
>> +            const const void *const *datas, const unsigned *lens)
>>   {
>> +   const uint8_t *data = datas[0];
>>      assert(vlc);
>> -   assert(data&&  len);
>> +   assert(array_size == 1); // TODO
>> +   assert(datas[0]&&  lens[0]);
> Adding an interface definition without an implementation usually only makes 
> sense when we could have more than one different implementation.
As the TODO says, I want to add support for array_size > 1 still, also next 
patch uses this interface, even if I didn't add the support for array_size > 1 
yet. If I don't continuously reset vlc it should work correctly even when a 
stream has multiple buffers.

>>
>>      vlc->buffer = 0;
>>      vlc->valid_bits = 0;
>> @@ -102,11 +104,11 @@ vl_vlc_init(struct vl_vlc *vlc, const uint8_t *data, 
>> unsigned len)
>>      while (pointer_to_uintptr(data)&  3) {
>>         vlc->buffer |= (uint64_t)*data<<  (56 - vlc->valid_bits);
>>         ++data;
>> -      --len;
>> +      --total_len;
>>         vlc->valid_bits += 8;
>>      }
>>      vlc->data = (uint32_t*)data;
>> -   vlc->end = (uint32_t*)(data + len);
>> +   vlc->end = (uint32_t*)(data + total_len);
>>
>>      vl_vlc_fillbits(vlc);
>>      vl_vlc_fillbits(vlc);
>> @@ -122,7 +124,7 @@ vl_vlc_bits_left(struct vl_vlc *vlc)
>>   static INLINE unsigned
>>   struct vl_vlc *vlc, unsigned num_bits)
>>   {
>> -   //assert(vlc->valid_bits>= num_bits);
>> +   assert(vlc->valid_bits>= num_bits || vl_vlc_bits_left(vlc)<  num_bits);
> Hui? bits_left is calculation the total number of bits left in the buffer, 
> while valid_bits is the number of currently loaded bits, so that check is 
> erroneous.
Yes, but if you are near the end of the stream it is possible that peekbits can 
extend beyond it when doing vlc decoding, hence the second check.
This is a special case for peekbits that would otherwise crash unnecessarily 
over DCT coefficients, any call that really consumes the bits will still fail.

>
>>
>>      return vlc->buffer>>  (64 - num_bits);
>>   }
>> @@ -130,7 +132,7 @@ vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits)
>>   static INLINE void
>>   vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits)
>>   {
>> -   //assert(vlc->valid_bits>  num_bits);
>> +   assert(vlc->valid_bits>= num_bits);
> Just commenting in all checks isn't such a good idea, since that affect 
> performance very badly, a define which enables all assertions at once at the 
> beginning of the file seems the better idea.
Sure.

>>
>>      vlc->buffer<<= num_bits;
>>      vlc->valid_bits -= num_bits;
>> @@ -141,7 +143,7 @@ vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits)
>>   {
>>      unsigned value;
>>
>> -   //assert(vlc->valid_bits>= num_bits);
>> +   assert(vlc->valid_bits>= num_bits);
>>
>>      value = vlc->buffer>>  (64 - num_bits);
>>      vl_vlc_eatbits(vlc, num_bits);
>> @@ -154,7 +156,7 @@ vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits)
>>   {
>>      signed value;
>>
>> -   //assert(vlc->valid_bits>= num_bits);
>> +   assert(vlc->valid_bits>= num_bits);
>>
>>      value = ((int64_t)vlc->buffer)>>  (64 - num_bits);
>>      vl_vlc_eatbits(vlc, num_bits);
>> @@ -167,7 +169,14 @@ vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct 
>> vl_vlc_entry *tbl, unsigned n
>>   {
>>      tbl += vl_vlc_peekbits(vlc, num_bits);
>>      vl_vlc_eatbits(vlc, tbl->length);
>> +   assert(tbl->length);
>>      return tbl->value;
>>   }
>>
>> +static INLINE void
>> +vl_vlc_bitalign(struct vl_vlc *vlc)
>> +{
>> +   vl_vlc_eatbits(vlc, vlc->valid_bits&  7);
>> +}
>> +
>>   #endif /* vl_vlc_h */
>>
>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>>
>
> Christian.
~Maarten

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to