Samples to test this? On Thu, Jul 22, 2021 at 10:27 PM <ffmpegandmahanstreamer@e.email> wrote:
> Overrides previous patch i submitted regarding this as the old patch I > submitted had a bug that is fixed in this one. > > --- > libavcodec/truemotion1.c | 206 +++++++++++++++++++++++++++++++++------ > 1 file changed, 174 insertions(+), 32 deletions(-) > > diff --git a/libavcodec/truemotion1.c b/libavcodec/truemotion1.c > index 32d8fb4005..b8e8379c74 100644 > --- a/libavcodec/truemotion1.c > +++ b/libavcodec/truemotion1.c > @@ -23,10 +23,11 @@ > * @file > * Duck TrueMotion v1 Video Decoder by > * Alex Beregszaszi and > - * Mike Melanson (melan...@pcisys.net) > + * Mike Melanson (m...@multimedia.cx) > * > - * The TrueMotion v1 decoder presently only decodes 16-bit TM1 data and > - * outputs RGB555 (or RGB565) data. 24-bit TM1 data is not supported yet. > + * The TrueMotion v1 decoder presently decodes 16-bit/24-bit TM1 data and > + * outputs RGB555 (or RGB565) data. > + * ffmpegandmahanstreamer@e.email: added sprite support 7/22/21 > */ > > #include <stdio.h> > @@ -56,9 +57,15 @@ typedef struct TrueMotion1Context { > > int flags; > int x, y, w, h; > + > + int xoffset; > + int yoffset; > + int spritew; > + int spriteh; > > uint32_t y_predictor_table[1024]; > uint32_t c_predictor_table[1024]; > + uint32_t a_predictor_table[1024]; > uint32_t fat_y_predictor_table[1024]; > uint32_t fat_c_predictor_table[1024]; > > @@ -66,6 +73,7 @@ typedef struct TrueMotion1Context { > int block_type; > int block_width; > int block_height; > + > > int16_t ydt[8]; > int16_t cdt[8]; > @@ -217,7 +225,10 @@ static int make_cdt16_entry(int p1, int p2, int16_t > *cdt) > lo = b + r; > return (lo + (lo * (1 << 16))) * 2; > } > - > +static int make_adt_entry(int p1, int p2) { > + int a = p1 + (p2 * 5); > + return ((a << 16) << 1); > +} > static int make_ydt24_entry(int p1, int p2, int16_t *ydt) > { > int lo, hi; > @@ -251,9 +262,12 @@ static void gen_vector_table15(TrueMotion1Context *s, > const uint8_t *sel_vector_ > make_ydt15_entry(delta_pair >> 4, delta_pair & 0xf, > s->ydt); > s->c_predictor_table[i+j] = 0xfffffffe & > make_cdt15_entry(delta_pair >> 4, delta_pair & 0xf, > s->cdt); > + s->a_predictor_table[i+j] = 0xfffffffe & > + make_adt_entry(delta_pair >> 4, delta_pair & 0xf); > } > s->y_predictor_table[i+(j-1)] |= 1; > s->c_predictor_table[i+(j-1)] |= 1; > + s->a_predictor_table[i+(j-1)] |= 1; > } > } > > @@ -272,9 +286,12 @@ static void gen_vector_table16(TrueMotion1Context *s, > const uint8_t *sel_vector_ > make_ydt16_entry(delta_pair >> 4, delta_pair & 0xf, > s->ydt); > s->c_predictor_table[i+j] = 0xfffffffe & > make_cdt16_entry(delta_pair >> 4, delta_pair & 0xf, > s->cdt); > + s->a_predictor_table[i+j] = 0xfffffffe & > + make_adt_entry(delta_pair >> 4, delta_pair & 0xf); > } > s->y_predictor_table[i+(j-1)] |= 1; > s->c_predictor_table[i+(j-1)] |= 1; > + s->a_predictor_table[i+(j-1)] |= 1; > } > } > > @@ -360,9 +377,19 @@ static int > truemotion1_decode_header(TrueMotion1Context *s) > s->flags = FLAG_KEYFRAME; > > if (s->flags & FLAG_SPRITE) { > - avpriv_request_sample(s->avctx, "Frame with sprite"); > - /* FIXME header.width, height, xoffset and yoffset aren't > initialized */ > - return AVERROR_PATCHWELCOME; > + // https://wiki.multimedia.cx/index.php/Duck_TrueMotion_1 > + header.xoffset = AV_RL16(&header_buffer[13]); > + header.yoffset = AV_RL16(&header_buffer[15]); > + header.width = AV_RL16(&header_buffer[17]); > + header.height = AV_RL16(&header_buffer[19]); > + s->w = header.xsize; > + s->h = header.ysize; > + s->spritew = header.width; > + s->spriteh = header.height; > + s->xoffset = header.xoffset; > + s->yoffset = header.yoffset; > + // avpriv_request_sample(s->avctx, "Frame with sprite"); > + // return AVERROR_PATCHWELCOME; > } else { > s->w = header.xsize; > s->h = header.ysize; > @@ -427,6 +454,9 @@ static int > truemotion1_decode_header(TrueMotion1Context *s) > * 32 pixels; divide width by 4 to obtain the number of change bits > and > * then round up to the nearest byte. */ > s->mb_change_bits_row_size = ((s->avctx->width >> (2 - width_shift)) > + 7) >> 3; > + if (s->flags & FLAG_SPRITE) { > + s->mb_change_bits_row_size = ((s->spritew >> 2) + 3) >> 2; > + } > > if ((header.deltaset != s->last_deltaset) || (header.vectable != > s->last_vectable)) > { > @@ -441,7 +471,7 @@ static int > truemotion1_decode_header(TrueMotion1Context *s) > > /* set up pointers to the other key data chunks */ > s->mb_change_bits = s->buf + header.header_size; > - if (s->flags & FLAG_KEYFRAME) { > + if ((s->flags & FLAG_KEYFRAME) && ((s->flags & FLAG_SPRITE) == 0)) { > /* no change bits specified for a keyframe; only index bytes */ > s->index_stream = s->mb_change_bits; > if (s->avctx->width * s->avctx->height / 2048 + > header.header_size > s->size) > @@ -451,6 +481,10 @@ static int > truemotion1_decode_header(TrueMotion1Context *s) > s->index_stream = s->mb_change_bits + > (s->mb_change_bits_row_size * (s->avctx->height >> 2)); > } > + if (s->flags & FLAG_SPRITE) { > + s->index_stream = s->mb_change_bits + > + (s->mb_change_bits_row_size * (s->spriteh >> > 2)); > + } > s->index_stream_size = s->size - (s->index_stream - s->buf); > > s->last_deltaset = header.deltaset; > @@ -593,6 +627,14 @@ do { > \ > } else \ > INC_INDEX; > > +#define APPLY_A_PREDICTOR() \ > + predictor_pair = s->a_predictor_table[index]; \ > + if (predictor_pair & 1) { \ > + GET_NEXT_INDEX() \ > + } else \ > + INC_INDEX; > + > +// a pred supposted to return predictor_pair_ 1, but result not used so > don't bother > #define APPLY_Y_PREDICTOR_24() \ > predictor_pair = s->y_predictor_table[index]; \ > horiz_pred += (predictor_pair >> 1); \ > @@ -660,20 +702,14 @@ static void > truemotion1_decode_16bit(TrueMotion1Context *s) > case 0: > /* if macroblock width is 2, apply C-Y-C-Y; else > * apply C-Y-Y */ > + APPLY_C_PREDICTOR(); > + APPLY_Y_PREDICTOR(); > + OUTPUT_PIXEL_PAIR(); > if (s->block_width == 2) { > APPLY_C_PREDICTOR(); > - APPLY_Y_PREDICTOR(); > - OUTPUT_PIXEL_PAIR(); > - APPLY_C_PREDICTOR(); > - APPLY_Y_PREDICTOR(); > - OUTPUT_PIXEL_PAIR(); > - } else { > - APPLY_C_PREDICTOR(); > - APPLY_Y_PREDICTOR(); > - OUTPUT_PIXEL_PAIR(); > - APPLY_Y_PREDICTOR(); > - OUTPUT_PIXEL_PAIR(); > } > + APPLY_Y_PREDICTOR(); > + OUTPUT_PIXEL_PAIR(); > break; > > case 1: > @@ -740,7 +776,118 @@ static void > truemotion1_decode_16bit(TrueMotion1Context *s) > current_line += s->frame->linesize[0]; > } > } > +static void truemotion1_decode_sprite(TrueMotion1Context *s) { > + int y; > + int pixels_left; /* remaining pixels on this line */ > + unsigned int predictor_pair; > + unsigned int horiz_pred; > + int is_tm = 0; > + int is_sprite = 0; > + int stride = s->avctx->width * (sizeof(unsigned int)); > + int spr_stride = s->spritew * sizeof(unsigned int); > + unsigned int *vert_pred; > + unsigned int *current_pixel_pair; > + unsigned char *current_line = s->frame->data[0]; > + current_line = current_line + (s->yoffset * stride >> 1) + s->xoffset; > + > + /* these variables are for managing the stream of macroblock change > bits */ > + const unsigned char *mb_change_bits = s->mb_change_bits; > + unsigned char mb_change_byte; > + unsigned char mb_change_byte_mask; > + int mb_change_index = 0; > + > + /* these variables are for managing the main index stream */ > + int index_stream_index = 0; /* yes, the index into the index stream > */ > + int index; > + > + /* clean out the line buffer */ > + memset(s->vert_pred, 0, stride); > + > + > + GET_NEXT_INDEX(); > + // av_log(s->avctx, AV_LOG_INFO, "is_keyframe: %d\n", keyframe); > + for (y = 0; y < s->spriteh; y++) { > + /* re-init variables for the next line iteration */ > + horiz_pred = 0; > + current_pixel_pair = (unsigned int *)current_line; > + vert_pred = s->vert_pred; > + mb_change_index = 0; > + mb_change_byte = mb_change_bits[mb_change_index++]; > + mb_change_byte_mask = 0x01; > + > + pixels_left = s->spritew; > + > + while (pixels_left > 0) { > + > + is_tm = !(((mb_change_byte & mb_change_byte_mask) == 0)); > + if (1) { > + mb_change_byte_mask <<= 1; > + > + /* next byte */ > + if (!mb_change_byte_mask) { > + mb_change_byte = mb_change_bits[mb_change_index++]; > + mb_change_byte_mask = 0x01; > + } > + } > + is_sprite = !(((mb_change_byte & mb_change_byte_mask) == 0) ); > + if (is_tm) { > + // av_log(s->avctx, AV_LOG_INFO, "is_tm\n"); > + if ((y & 3) == 0) { > + APPLY_C_PREDICTOR(); > + } > + APPLY_Y_PREDICTOR(); > + OUTPUT_PIXEL_PAIR(); > + > + APPLY_Y_PREDICTOR(); > + OUTPUT_PIXEL_PAIR(); > + > + } else if (is_sprite) { //is_sprite > + // av_log(s->avctx, AV_LOG_INFO, "is_sprite\n"); > + if ((y & 3) == 0) { > + // av_log(s->avctx, AV_LOG_INFO, "called c pred\n"); > + APPLY_C_PREDICTOR(); > + } > + APPLY_Y_PREDICTOR(); > + APPLY_A_PREDICTOR(); > + OUTPUT_PIXEL_PAIR(); > + APPLY_Y_PREDICTOR(); > + APPLY_A_PREDICTOR(); > + OUTPUT_PIXEL_PAIR(); > + > + } else { > + // av_log(s->avctx, AV_LOG_INFO, "nothing, is_sprite: %d, > is_tm : %d\n", is_sprite, is_tm); > + horiz_pred = 0; > + *current_pixel_pair++ = 0; > + *current_pixel_pair++ = 0; > + > + *vert_pred++ = 0; > + *vert_pred++ = 0; > + > + } > + if (1) { > + mb_change_byte_mask <<= 1; > + > + /* next byte */ > + if (!mb_change_byte_mask) { > + mb_change_byte = mb_change_bits[mb_change_index++]; > + mb_change_byte_mask = 0x01; > + } > + } > + pixels_left -= 4; > + > + > + } > + /* next change row */ > + if (((y + 1) & 3) == 0) > + mb_change_bits += s->mb_change_bits_row_size; > + > > + current_line += stride; > + } > + // av_log(s->avctx, AV_LOG_INFO, "done\n"); > + > + > +} > static void truemotion1_decode_24bit(TrueMotion1Context *s) > { > int y; > @@ -786,20 +933,14 @@ static void > truemotion1_decode_24bit(TrueMotion1Context *s) > case 0: > /* if macroblock width is 2, apply C-Y-C-Y; else > * apply C-Y-Y */ > + APPLY_C_PREDICTOR_24(); > + APPLY_Y_PREDICTOR_24(); > + OUTPUT_PIXEL_PAIR(); > if (s->block_width == 2) { > APPLY_C_PREDICTOR_24(); > - APPLY_Y_PREDICTOR_24(); > - OUTPUT_PIXEL_PAIR(); > - APPLY_C_PREDICTOR_24(); > - APPLY_Y_PREDICTOR_24(); > - OUTPUT_PIXEL_PAIR(); > - } else { > - APPLY_C_PREDICTOR_24(); > - APPLY_Y_PREDICTOR_24(); > - OUTPUT_PIXEL_PAIR(); > - APPLY_Y_PREDICTOR_24(); > - OUTPUT_PIXEL_PAIR(); > } > + APPLY_Y_PREDICTOR_24(); > + OUTPUT_PIXEL_PAIR(); > break; > > case 1: > @@ -884,8 +1025,9 @@ static int truemotion1_decode_frame(AVCodecContext > *avctx, > > if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) > return ret; > - > - if (compression_types[s->compression].algorithm == ALGO_RGB24H) { > + if (s->flags & FLAG_SPRITE) { > + truemotion1_decode_sprite(s); > + } else if (compression_types[s->compression].algorithm == > ALGO_RGB24H) { > truemotion1_decode_24bit(s); > } else if (compression_types[s->compression].algorithm != ALGO_NOP) { > truemotion1_decode_16bit(s); > -- > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe". > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".