[FFmpeg-devel] [PATCH] Escape 124 (RPL) decoder rev3
Michael Niedermayer
michaelni
Sat Mar 29 19:47:30 CET 2008
On Sat, Mar 29, 2008 at 01:17:19AM -0700, Eli Friedman wrote:
> Per subject, third revision of Escape 124 decoder.
[...]
> + uint32_t mask_bits = get_bits(gb, 4);
> + uint32_t color0 = get_bits(gb, 15);
> + uint32_t color1 = get_bits(gb, 15);
normal unsigned is enough for these
[...]
> +static SuperBlock read_superblock_from_buffer(
> + uint16_t* frame_data, uint32_t stride,
> + uint32_t superblock_row_index, uint32_t superblock_col_index) {
> + unsigned y;
> + SuperBlock sb;
> + // The first frame defaults to black
> + if (!frame_data)
> + return (SuperBlock) { { { { 0 } } } };
> + frame_data += stride * 8 * superblock_row_index +
> + 8 * superblock_col_index;
As said in a previous review, vertical align these please.
> + for(y=0; y<8; y++)
> + memcpy(sb.pixels + y * 8, frame_data + y * stride, sizeof(uint16_t)*8);
> + return sb;
This copies the data twice.
> +}
> +
> +static void write_superblock_to_buffer(
> + uint16_t* frame_data, uint32_t stride,
> + uint32_t superblock_row_index, uint32_t superblock_col_index,
> + SuperBlock sb) {
> + unsigned y;
> + frame_data += stride * 8 * superblock_row_index +
> + 8 * superblock_col_index;
> + for(y=0; y<8; y++)
> + memcpy(frame_data + y * stride, sb.pixels + y * 8, sizeof(uint16_t)*8);
> +}
This has the same problem, it also copies the data twice.
> +
> +
> +static MacroBlock decode_macroblock(Escape124Context* s, GetBitContext* gb,
> + int* codebook_index, int superblock_index) {
> + // This funxtion reads a maximum of 22 bits; the callers
^
typo
[...]
> + block_index += (1 << s->codebooks[1]->depth) * superblock_index;
This can be done without the multiply.
[...]
> +static void insert_mb_into_sb(SuperBlock* sb, MacroBlock mb, unsigned index) {
> + unsigned base = (index / 4) * 16 + (index % 4) * 2;
> + sb->pixels[base] = mb.pixels[0];
> + sb->pixels[base+1] = mb.pixels[1];
> + sb->pixels[base+8] = mb.pixels[2];
> + sb->pixels[base+9] = mb.pixels[3];
static inline void insert_mb_into_sb(SuperBlock* sb, MacroBlock mb, unsigned index) {
static const uint8_t base_tab[]={...
unsigned base = base_tab[index];
uint32_t *dst= sb->pixels;
dst[base ]= ((uint32_t*)mb.pixels)[0]
dst[base+4]= ((uint32_t*)mb.pixels)[1]
[...]
> + frame_flags = get_bits_long(&gb, 32);
> + frame_size = get_bits_long(&gb, 32);
vertical align
> +
> + // Leave last frame unchanged
> + // FIXME: Is this necessary? I haven't seen it in any real samples
> + if (!(frame_flags & 0x114) || !(frame_flags & 0x7800000)) {
> + av_log(NULL, AV_LOG_DEBUG, "Skipping frame\n");
> +
> + *data_size = sizeof(AVFrame);
> + *(AVFrame*)data = s->frame;
> +
> + return frame_size;
> + }
> +
> + for (i = 0; i < 3; i++) {
> + if (frame_flags & (1 << (17 + i))) {
> + if (i == 0) {
> + // This is the most basic codebook: pow(2,depth) entries for
> + // a depth-length key
> + cb_depth = get_bits(&gb, 4);
> + cb_size = 1 << cb_depth;
> + cb_alloc_size = cb_size;
> + } else if (i == 1) {
> + // This codebook varies per superblock
> + // FIXME: I don't think this handles integer overflow
> + // properly
> + cb_depth = get_bits(&gb, 4);
> + cb_size = s->num_superblocks << cb_depth;
> + cb_alloc_size = cb_size;
> + } else {
> + // This codebook can be cut off at places other than
> + // powers of 2, leaving some of the entries undefined.
> + cb_size = get_bits_long(&gb, 20);
> + cb_depth = av_log2(cb_size - 1) + 1;
> + cb_alloc_size = 1 << cb_depth;
> + }
What is the use of having cb_alloc_size > cb_size ?
And theres some common code in the above which can be factored out
> + av_free(s->codebooks[i]);
> + s->codebooks[i] = unpack_codebook(&gb, cb_depth, cb_size,
> + cb_alloc_size);
> + if (!s->codebooks[i])
> + return -1;
> + }
> + }
> +
> + if (avctx->get_buffer(avctx, &new_frame)) {
You must set reference before calling get_buffer() if you read from the frame
later.
> + av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
> + return -1;
> + }
> +
> + new_frame_data = (uint16_t*)new_frame.data[0];
> + new_stride = new_frame.linesize[0] / 2;
> + old_frame_data = (uint16_t*)s->frame.data[0];
> + old_stride = s->frame.linesize[0] / 2;
> +
> + superblocks_per_row = avctx->width / 8;
> +
> + cb_index = 1;
> + superblock_index = 0;
> + superblock_row_index = 0;
> + superblock_col_index = 0;
initialization and declaration can be merged
> +
> + do {
> + uint32_t multi_mask = 0;
> + // Note that this call will make us skip the rest of the blocks
> + // if the frame prematurely ends
> + uint32_t skip = decode_skip_count(&gb);
> +
> + for (i = 0; i < skip && superblock_index < s->num_superblocks;
> + i++, superblock_index++) {
> + sb = read_superblock_from_buffer(old_frame_data, old_stride,
> + superblock_row_index,
> + superblock_col_index);
> + write_superblock_to_buffer(new_frame_data, new_stride,
> + superblock_row_index,
> + superblock_col_index, sb);
> + superblock_col_index++;
> + if (superblock_col_index == superblocks_per_row) {
> + superblock_row_index++;
> + superblock_col_index = 0;
> + }
> + }
> +
> + if (superblock_index >= s->num_superblocks)
> + break;
> +
> + sb = read_superblock_from_buffer(old_frame_data, old_stride,
> + superblock_row_index,
> + superblock_col_index);
> +
> + while (can_safely_read(&gb, 1) && !get_bits1(&gb)) {
> + uint32_t mask;
> + mb = decode_macroblock(s, &gb, &cb_index, superblock_index);
> + mask = get_bits(&gb, 16);
> + multi_mask |= mask;
> + for (i = 0; i < 16; i++) {
> + if (mask & mask_matrix[i]) {
> + insert_mb_into_sb(&sb, mb, i);
> + }
> + }
> + }
> +
> + if (can_safely_read(&gb, 1) && !get_bits1(&gb)) {
i think the can_safely_read is unneeded here.
> + uint32_t inv_mask;
> + inv_mask = get_bits(&gb, 4);
declaration and initialization can be merged
> + for (i = 0; i < 4; i++) {
> + if (inv_mask & (1 << i)) {
> + multi_mask ^= 0xF << i*4;
> + } else {
> + multi_mask ^= get_bits(&gb, 4) << i*4;
> + }
> + }
> +
> + for (i = 0; i < 16; i++) {
> + if (!can_safely_read(&gb, 1))
> + break;
> + if (multi_mask & mask_matrix[i]) {
the can_safely_read() should be done after the mask check its redundant before.
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
Opposition brings concord. Out of discord comes the fairest harmony.
-- Heraclitus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080329/6980eb05/attachment.pgp>
More information about the ffmpeg-devel
mailing list