You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	Merge commit '470cd0c5fe6337b6cb5276b3f84400999450fc1b'
* commit '470cd0c5fe6337b6cb5276b3f84400999450fc1b': Add TrueMotion 2.0 Real Time decoder Merged-by: Clément Bœsch <u@pkh.me>
This commit is contained in:
		| @@ -679,6 +679,8 @@ following image formats are supported: | ||||
|     @tab fourcc: DUCK | ||||
| @item Duck TrueMotion 2.0    @tab     @tab  X | ||||
|     @tab fourcc: TM20 | ||||
| @item Duck TrueMotion 2.0 RT @tab     @tab  X | ||||
|     @tab fourcc: TR20 | ||||
| @item DV (Digital Video)     @tab  X  @tab  X | ||||
| @item Dxtory capture format  @tab     @tab  X | ||||
| @item Feeble Files/ScummVM DXA  @tab     @tab  X | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /* | ||||
|  * Duck TrueMotion 2.0 Real Time Decoder | ||||
|  * Duck TrueMotion 2.0 Real Time decoder | ||||
|  * | ||||
|  * This file is part of FFmpeg. | ||||
|  * | ||||
| @@ -22,51 +22,68 @@ | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #define BITSTREAM_READER_LE | ||||
| #include "avcodec.h" | ||||
| #include "get_bits.h" | ||||
| #include "internal.h" | ||||
| #include "libavutil/imgutils.h" | ||||
| #include "libavutil/internal.h" | ||||
| #include "libavutil/intreadwrite.h" | ||||
| #include "libavutil/mem.h" | ||||
|  | ||||
| #define BITSTREAM_READER_LE | ||||
| #include "avcodec.h" | ||||
| #include "get_bits.h" | ||||
| #include "internal.h" | ||||
|  | ||||
| typedef struct TrueMotion2RTContext { | ||||
|     GetBitContext gb; | ||||
|     const uint8_t *buf; | ||||
|     int size; | ||||
|     int delta_size; | ||||
|     int hscale; | ||||
| } TrueMotion2RTContext; | ||||
|  | ||||
| static av_cold int decode_init(AVCodecContext *avctx) | ||||
| { | ||||
|     avctx->pix_fmt = AV_PIX_FMT_YUV410P; | ||||
|     return 0; | ||||
| } | ||||
| static const int16_t delta_tab2[] = { | ||||
|     5, -7, 36, -36, | ||||
| }; | ||||
|  | ||||
| /* Returns the number of bytes consumed from the bytestream. Returns -1 if | ||||
|  * there was an error while decoding the header */ | ||||
| static int truemotion2rt_decode_header(AVCodecContext *avctx) | ||||
| static const int16_t delta_tab3[] = { | ||||
|     2, -3, 8, -8, 18, -18, 36, -36, | ||||
| }; | ||||
|  | ||||
| static const int16_t delta_tab4[] = { | ||||
|     1, -1, 2, -3, 8, -8, 18, -18, 36, -36, 54, -54, 96, -96, 144, -144, | ||||
| }; | ||||
|  | ||||
| static const int16_t *const delta_tabs[] = { | ||||
|     delta_tab2, delta_tab3, delta_tab4, | ||||
| }; | ||||
|  | ||||
| /* Returns the number of bytes consumed from the bytestream, or | ||||
|  * AVERROR_INVALIDDATA if there was an error while decoding the header. */ | ||||
| static int truemotion2rt_decode_header(AVCodecContext *avctx, AVPacket *avpkt) | ||||
| { | ||||
|     TrueMotion2RTContext *s = avctx->priv_data; | ||||
|     uint8_t header_buffer[128] = { 0 };  /* logical maximum size of the header */ | ||||
|     int i, header_size; | ||||
|     int header_size; | ||||
|     uint8_t header_buffer[128] = { 0 };  /* logical maximum header size */ | ||||
|     const uint8_t *buf = avpkt->data; | ||||
|     int size = avpkt->size; | ||||
|     int i; | ||||
|  | ||||
|     header_size = ((s->buf[0] >> 5) | (s->buf[0] << 3)) & 0x7f; | ||||
|     if (size < 1) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size); | ||||
|         return AVERROR_INVALIDDATA; | ||||
|     } | ||||
|  | ||||
|     header_size = ((buf[0] >> 5) | (buf[0] << 3)) & 0x7f; | ||||
|     if (header_size < 10) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "invalid header size (%d)\n", header_size); | ||||
|         return AVERROR_INVALIDDATA; | ||||
|     } | ||||
|  | ||||
|     if (header_size + 1 > s->size) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "Input packet too small.\n"); | ||||
|     if (header_size + 1 > size) { | ||||
|         av_log(avctx, AV_LOG_ERROR, "input packet too small (%d)\n", size); | ||||
|         return AVERROR_INVALIDDATA; | ||||
|     } | ||||
|  | ||||
|     /* unscramble the header bytes with a XOR operation */ | ||||
|     for (i = 1; i < header_size; i++) | ||||
|         header_buffer[i - 1] = s->buf[i] ^ s->buf[i + 1]; | ||||
|         header_buffer[i - 1] = buf[i] ^ buf[i + 1]; | ||||
|  | ||||
|     s->delta_size = header_buffer[1]; | ||||
|     s->hscale = 1 + !!header_buffer[3]; | ||||
| @@ -76,47 +93,30 @@ static int truemotion2rt_decode_header(AVCodecContext *avctx) | ||||
|     avctx->height = AV_RL16(header_buffer + 5); | ||||
|     avctx->width  = AV_RL16(header_buffer + 7); | ||||
|  | ||||
|     av_log(avctx, AV_LOG_DEBUG, "Header size: %d\n", header_size); | ||||
|     return header_size; | ||||
| } | ||||
|  | ||||
| static const int16_t delta_tab4[] = { | ||||
|     1, -1, 2, -3, 8, -8, 18, -18, 36, -36, 54, -54, 96, -96, 144, -144 | ||||
| }; | ||||
|  | ||||
| static const int16_t delta_tab3[] = { | ||||
|     2, -3, 8, -8, 18, -18, 36, -36 | ||||
| }; | ||||
|  | ||||
| static const int16_t delta_tab2[] = { | ||||
|     5, -7, 36, -36 | ||||
| }; | ||||
|  | ||||
| static const int16_t *const delta_tabs[] = { | ||||
|     delta_tab2, delta_tab3, delta_tab4, | ||||
| }; | ||||
|  | ||||
| static int decode_frame(AVCodecContext *avctx, | ||||
|                         void *data, int *got_frame, | ||||
|                         AVPacket *avpkt) | ||||
| static int truemotion2rt_decode_frame(AVCodecContext *avctx, void *data, | ||||
|                                       int *got_frame, AVPacket *avpkt) | ||||
| { | ||||
|     TrueMotion2RTContext *s = avctx->priv_data; | ||||
|     const uint8_t *buf = avpkt->data; | ||||
|     int ret, buf_size = avpkt->size; | ||||
|     AVFrame * const p = data; | ||||
|     GetBitContext *gb = &s->gb; | ||||
|     uint8_t *dst; | ||||
|     int x, y, delta_mode; | ||||
|     int ret; | ||||
|  | ||||
|     s->buf = buf; | ||||
|     s->size = buf_size; | ||||
|  | ||||
|     if ((ret = truemotion2rt_decode_header(avctx)) < 0) | ||||
|     ret = truemotion2rt_decode_header(avctx, avpkt); | ||||
|     if (ret < 0) | ||||
|         return ret; | ||||
|  | ||||
|     if ((ret = init_get_bits8(gb, buf + ret, buf_size - ret)) < 0) | ||||
|     ret = init_get_bits8(gb, avpkt->data + ret, avpkt->size - ret); | ||||
|     if (ret < 0) | ||||
|         return ret; | ||||
|  | ||||
|     if ((ret = ff_get_buffer(avctx, p, 0)) < 0) | ||||
|     ret = ff_get_buffer(avctx, p, 0); | ||||
|     if (ret < 0) | ||||
|         return ret; | ||||
|  | ||||
|     skip_bits(gb, 32); | ||||
| @@ -134,9 +134,8 @@ static int decode_frame(AVCodecContext *avctx, | ||||
|     if (s->hscale > 1) { | ||||
|         dst = p->data[0]; | ||||
|         for (y = 0; y < avctx->height; y++) { | ||||
|             for (x = 1; x < avctx->width; x += s->hscale) { | ||||
|             for (x = 1; x < avctx->width; x += s->hscale) | ||||
|                 dst[x] = dst[x - 1]; | ||||
|             } | ||||
|             dst += p->linesize[0]; | ||||
|         } | ||||
|     } | ||||
| @@ -161,9 +160,8 @@ static int decode_frame(AVCodecContext *avctx, | ||||
|     if (s->hscale > 1) { | ||||
|         dst = p->data[1]; | ||||
|         for (y = 0; y < avctx->height >> 2; y++) { | ||||
|             for (x = 1; x < avctx->width >> 2; x += s->hscale) { | ||||
|             for (x = 1; x < avctx->width >> 2; x += s->hscale) | ||||
|                 dst[x] = dst[x - 1]; | ||||
|             } | ||||
|             dst += p->linesize[1]; | ||||
|         } | ||||
|     } | ||||
| @@ -188,9 +186,8 @@ static int decode_frame(AVCodecContext *avctx, | ||||
|     if (s->hscale > 1) { | ||||
|         dst = p->data[2]; | ||||
|         for (y = 0; y < avctx->height >> 2; y++) { | ||||
|             for (x = 1; x < avctx->width >> 2; x += s->hscale) { | ||||
|             for (x = 1; x < avctx->width >> 2; x += s->hscale) | ||||
|                 dst[x] = dst[x - 1]; | ||||
|             } | ||||
|             dst += p->linesize[2]; | ||||
|         } | ||||
|     } | ||||
| @@ -204,9 +201,15 @@ static int decode_frame(AVCodecContext *avctx, | ||||
|  | ||||
|     p->pict_type = AV_PICTURE_TYPE_I; | ||||
|     p->key_frame = 1; | ||||
|     *got_frame   = 1; | ||||
|     *got_frame = 1; | ||||
|  | ||||
|     return buf_size; | ||||
|     return avpkt->size; | ||||
| } | ||||
|  | ||||
| static av_cold int truemotion2rt_decode_init(AVCodecContext *avctx) | ||||
| { | ||||
|     avctx->pix_fmt = AV_PIX_FMT_YUV410P; | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| AVCodec ff_truemotion2rt_decoder = { | ||||
| @@ -215,7 +218,8 @@ AVCodec ff_truemotion2rt_decoder = { | ||||
|     .type           = AVMEDIA_TYPE_VIDEO, | ||||
|     .id             = AV_CODEC_ID_TRUEMOTION2RT, | ||||
|     .priv_data_size = sizeof(TrueMotion2RTContext), | ||||
|     .init           = decode_init, | ||||
|     .decode         = decode_frame, | ||||
|     .init           = truemotion2rt_decode_init, | ||||
|     .decode         = truemotion2rt_decode_frame, | ||||
|     .capabilities   = AV_CODEC_CAP_DR1, | ||||
|     .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE, | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user