📄 truemotion1.c
字号:
// else// avctx->pix_fmt = PIX_FMT_RGB555; avctx->has_b_frames = 0; s->frame.data[0] = s->prev_frame.data[0] = NULL; /* there is a vertical predictor for each pixel in a line; each vertical * predictor is 0 to start with */ s->vert_pred = (unsigned int *)av_malloc(s->avctx->width * sizeof(unsigned short)); return 0;}/*Block decoding order:dxi: Y-Ydxic: Y-C-Ydxic2: Y-C-Y-Chres,vres,i,i%vres (0 < i < 4)2x2 0: 0 dxic22x2 1: 1 dxi2x2 2: 0 dxic22x2 3: 1 dxi2x4 0: 0 dxic22x4 1: 1 dxi2x4 2: 2 dxi2x4 3: 3 dxi4x2 0: 0 dxic4x2 1: 1 dxi4x2 2: 0 dxic4x2 3: 1 dxi4x4 0: 0 dxic4x4 1: 1 dxi4x4 2: 2 dxi4x4 3: 3 dxi*/#define GET_NEXT_INDEX() \{\ if (index_stream_index >= s->index_stream_size) { \ av_log(s->avctx, AV_LOG_INFO, " help! truemotion1 decoder went out of bounds\n"); \ return; \ } \ index = s->index_stream[index_stream_index++] * 4; \}#define APPLY_C_PREDICTOR() \ predictor_pair = s->c_predictor_table[index]; \ horiz_pred += (predictor_pair >> 1); \ if (predictor_pair & 1) { \ GET_NEXT_INDEX() \ if (!index) { \ GET_NEXT_INDEX() \ predictor_pair = s->c_predictor_table[index]; \ horiz_pred += ((predictor_pair >> 1) * 5); \ if (predictor_pair & 1) \ GET_NEXT_INDEX() \ else \ index++; \ } \ } else \ index++;#define APPLY_C_PREDICTOR_24() \ predictor_pair = s->c_predictor_table[index]; \ c_horiz_pred += (predictor_pair >> 1); \ if (predictor_pair & 1) { \ GET_NEXT_INDEX() \ if (!index) { \ GET_NEXT_INDEX() \ predictor_pair = s->fat_c_predictor_table[index]; \ c_horiz_pred += (predictor_pair >> 1); \ if (predictor_pair & 1) \ GET_NEXT_INDEX() \ else \ index++; \ } \ } else \ index++; // c_last+coff = clast+c_horiz_pred;#define APPLY_Y_PREDICTOR() \ predictor_pair = s->y_predictor_table[index]; \ horiz_pred += (predictor_pair >> 1); \ if (predictor_pair & 1) { \ GET_NEXT_INDEX() \ if (!index) { \ GET_NEXT_INDEX() \ predictor_pair = s->y_predictor_table[index]; \ horiz_pred += ((predictor_pair >> 1) * 5); \ if (predictor_pair & 1) \ GET_NEXT_INDEX() \ else \ index++; \ } \ } else \ index++;#define APPLY_Y_PREDICTOR_24() \ predictor_pair = s->y_predictor_table[index]; \ horiz_pred += (predictor_pair >> 1); \ if (predictor_pair & 1) { \ GET_NEXT_INDEX() \ if (!index) { \ GET_NEXT_INDEX() \ predictor_pair = s->fat_y_predictor_table[index]; \ horiz_pred += (predictor_pair >> 1); \ if (predictor_pair & 1) \ GET_NEXT_INDEX() \ else \ index++; \ } \ } else \ index++;#define OUTPUT_PIXEL_PAIR() \ *current_pixel_pair = *vert_pred + horiz_pred; \ *vert_pred++ = *current_pixel_pair++; \ prev_pixel_pair++;static void truemotion1_decode_16bit(TrueMotion1Context *s){ int y; int pixels_left; /* remaining pixels on this line */ unsigned int predictor_pair; unsigned int horiz_pred; unsigned int *vert_pred; unsigned int *current_pixel_pair; unsigned int *prev_pixel_pair; unsigned char *current_line = s->frame.data[0]; unsigned char *prev_line = s->prev_frame.data[0]; int keyframe = s->flags & FLAG_KEYFRAME; /* these variables are for managing the stream of macroblock change bits */ unsigned char *mb_change_bits = s->mb_change_bits; unsigned char mb_change_byte; unsigned char mb_change_byte_mask; int mb_change_index; /* 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, s->avctx->width * sizeof(unsigned short)); GET_NEXT_INDEX(); for (y = 0; y < s->avctx->height; y++) { /* re-init variables for the next line iteration */ horiz_pred = 0; current_pixel_pair = (unsigned int *)current_line; prev_pixel_pair = (unsigned int *)prev_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->avctx->width; while (pixels_left > 0) { if (keyframe || ((mb_change_byte & mb_change_byte_mask) == 0)) { switch (y & 3) { case 0: /* if macroblock width is 2, apply C-Y-C-Y; else * apply C-Y-Y */ 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(); } break; case 1: case 3: /* always apply 2 Y predictors on these iterations */ APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); break; case 2: /* this iteration might be C-Y-C-Y, Y-Y, or C-Y-Y * depending on the macroblock type */ if (s->block_type == BLOCK_2x2) { APPLY_C_PREDICTOR(); APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); APPLY_C_PREDICTOR(); APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); } else if (s->block_type == BLOCK_4x2) { APPLY_C_PREDICTOR(); APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); } else { APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); APPLY_Y_PREDICTOR(); OUTPUT_PIXEL_PAIR(); } break; } } else { /* skip (copy) four pixels, but reassign the horizontal * predictor */ *current_pixel_pair = *prev_pixel_pair++; *vert_pred++ = *current_pixel_pair++; *current_pixel_pair = *prev_pixel_pair++; horiz_pred = *current_pixel_pair - *vert_pred; *vert_pred++ = *current_pixel_pair++; } if (!keyframe) { 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 += s->frame.linesize[0]; prev_line += s->prev_frame.linesize[0]; }}static void truemotion1_decode_24bit(TrueMotion1Context *s){ int y; int pixels_left; /* remaining pixels on this line */ unsigned int predictor_pair; unsigned int horiz_pred; unsigned int c_horiz_pred; unsigned int *vert_pred; unsigned int *current_pixel_pair; unsigned int *prev_pixel_pair; unsigned char *current_line = s->frame.data[0]; unsigned char *prev_line = s->prev_frame.data[0]; int keyframe = s->flags & FLAG_KEYFRAME; /* these variables are for managing the stream of macroblock change bits */ unsigned char *mb_change_bits = s->mb_change_bits; unsigned char mb_change_byte; unsigned char mb_change_byte_mask; int mb_change_index; /* 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, s->avctx->width * sizeof(unsigned short)); GET_NEXT_INDEX(); for (y = 0; y < s->avctx->height; y++) { /* re-init variables for the next line iteration */ horiz_pred = c_horiz_pred = 0; current_pixel_pair = (unsigned int *)current_line; prev_pixel_pair = (unsigned int *)prev_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->avctx->width; while (pixels_left > 0) { if (keyframe || ((mb_change_byte & mb_change_byte_mask) == 0)) { switch (y & 3) { case 0: /* if macroblock width is 2, apply C-Y-C-Y; else * apply C-Y-Y */ if (s->block_width == 2) { APPLY_C_PREDICTOR_24(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); APPLY_C_PREDICTOR_24(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); } else { APPLY_C_PREDICTOR_24(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); } break; case 1: case 3: /* always apply 2 Y predictors on these iterations */ APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR(); break; case 2: /* this iteration might be C-Y-C-Y, Y-Y, or C-Y-Y * depending on the macroblock type */ if (s->block_type == BLOCK_2x2) { APPLY_C_PREDICTOR_24(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); APPLY_C_PREDICTOR_24(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); } else if (s->block_type == BLOCK_4x2) { APPLY_C_PREDICTOR_24(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR();// OUTPUT_PIXEL_PAIR_24_C(); } else { APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR(); APPLY_Y_PREDICTOR_24(); OUTPUT_PIXEL_PAIR(); } break; } } else { /* skip (copy) four pixels, but reassign the horizontal * predictor */ *current_pixel_pair = *prev_pixel_pair++; *vert_pred++ = *current_pixel_pair++; *current_pixel_pair = *prev_pixel_pair++; horiz_pred = *current_pixel_pair - *vert_pred;// c_horiz_pred = *current_pixel_pair - *vert_pred; *vert_pred++ = *current_pixel_pair++; } if (!keyframe) { 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 += s->frame.linesize[0]; prev_line += s->prev_frame.linesize[0]; }}static int truemotion1_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size){ TrueMotion1Context *s = (TrueMotion1Context *)avctx->priv_data; s->buf = buf; s->size = buf_size; if (truemotion1_decode_header(s) == -1) return -1; s->frame.reference = 1; if (avctx->get_buffer(avctx, &s->frame) < 0) { av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed\n"); return -1; } /* check for a do-nothing frame and copy the previous frame */ if (compression_types[s->compression].algorithm == ALGO_NOP) { memcpy(s->frame.data[0], s->prev_frame.data[0], s->frame.linesize[0] * s->avctx->height); } else if (compression_types[s->compression].algorithm == ALGO_RGB24H) { truemotion1_decode_24bit(s); } else { truemotion1_decode_16bit(s); } if (s->prev_frame.data[0]) avctx->release_buffer(avctx, &s->prev_frame); /* shuffle frames */ s->prev_frame = s->frame; *data_size = sizeof(AVFrame); *(AVFrame*)data = s->frame; /* report that the buffer was completely consumed */ return buf_size;}static int truemotion1_decode_end(AVCodecContext *avctx){ TrueMotion1Context *s = (TrueMotion1Context *)avctx->priv_data; /* release the last frame */ if (s->prev_frame.data[0]) avctx->release_buffer(avctx, &s->prev_frame); av_free(s->vert_pred); return 0;}AVCodec truemotion1_decoder = { "truemotion1", CODEC_TYPE_VIDEO, CODEC_ID_TRUEMOTION1, sizeof(TrueMotion1Context), truemotion1_decode_init, NULL, truemotion1_decode_end, truemotion1_decode_frame, CODEC_CAP_DR1,};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -