History

avcodec/eatgq: decode motion vector macroblocks

Peter Ross committed 2 years ago

Commit 2f34b151 parent 10c02de2 files · +51 −5Browse files

Showing the changes to libavcodec (2 of 2 files). Show all

Unified · Split

2 files
  1. libavcodec/codec_desc.c +1 −1
  2. libavcodec/eatgq.c +50 −4
libavcodec/codec_desc.c+1−1
@@ -905,7 +905,7 @@ static const AVCodecDescriptor codec_descriptors[] = { · 904 unmodified lines
905905 .type = AVMEDIA_TYPE_VIDEO,
906906 .name = "tgq",
907907 .long_name = NULL_IF_CONFIG_SMALL("Electronic Arts TGQ video"),
908− .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY,
908+ .props = AV_CODEC_PROP_LOSSY,
909909 },
910910 {
911911 .id = AV_CODEC_ID_TQI,
libavcodec/eatgq.c+50−4
@@ -36,12 +36,14 @@ · 35 unmodified lines
3636 #include "avcodec.h"
3737 #include "bytestream.h"
3838 #include "codec_internal.h"
39+#include "copy_block.h"
3940 #include "decode.h"
4041 #include "eaidct.h"
4142 #include "get_bits.h"
4243
4344 typedef struct TgqContext {
4445 AVCodecContext *avctx;
46+ AVFrame *last_frame;
4547 int width, height;
4648 int qtable[64];
4749 DECLARE_ALIGNED(16, int16_t, block)[6][64];
@@ -53,6 +55,9 @@ static av_cold int tgq_decode_init(AVCodecContext *avctx) · 5 unmodified lines
5355 s->avctx = avctx;
5456 avctx->framerate = (AVRational){ 15, 1 };
5557 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
58+ s->last_frame = av_frame_alloc();
59+ if (!s->last_frame)
60+ return AVERROR(ENOMEM);
5661 return 0;
5762 }
5863
@@ -173,7 +178,33 @@ static int tgq_decode_mb(TgqContext *s, GetByteContext *gbyte, · 114 unmodified lines
173178 tgq_idct_put_mb(s, s->block, frame, mb_x, mb_y);
174179 bytestream2_skip(gbyte, mode);
175180 } else {
176− if (mode == 3) {
181+ if (mode == 1) {
182+ int x, y;
183+ int mv = bytestream2_get_byte(gbyte);
184+ int mv_x = mv >> 4;
185+ int mv_y = mv & 0x0F;
186+ if (!s->last_frame->data[0]) {
187+ av_log(s->avctx, AV_LOG_ERROR, "missing reference frame\n");
188+ return -1;
189+ }
190+ if (mv_x >= 8) mv_x -= 16;
191+ if (mv_y >= 8) mv_y -= 16;
192+ x = mb_x * 16 - mv_x;
193+ y = mb_y * 16 - mv_y;
194+ if (x < 0 || x + 16 > s->width || y < 0 || y + 16 > s->height) {
195+ av_log(s->avctx, AV_LOG_ERROR, "invalid motion vector\n");
196+ return -1;
197+ }
198+ copy_block16(frame->data[0] + (mb_y * 16 * frame->linesize[0]) + mb_x * 16,
199+ s->last_frame->data[0] + y * s->last_frame->linesize[0] + x,
200+ frame->linesize[0], s->last_frame->linesize[0], 16);
201+ for (int p = 1; p < 3; p++)
202+ copy_block8(frame->data[p] + (mb_y * 8 * frame->linesize[p]) + mb_x * 8,
203+ s->last_frame->data[p] + (y >> 1) * s->last_frame->linesize[p] + (x >> 1),
204+ frame->linesize[p], s->last_frame->linesize[p], 8);
205+ frame->flags &= ~AV_FRAME_FLAG_KEY;
206+ return 0;
207+ } else if (mode == 3) {
177208 memset(dc, bytestream2_get_byte(gbyte), 4);
178209 dc[4] = bytestream2_get_byte(gbyte);
179210 dc[5] = bytestream2_get_byte(gbyte);
@@ -228,9 +259,12 @@ static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame, · 48 unmodified lines
228259 s->height = bytestream2_get_le16u(&gbyte);
229260 }
230261
231− ret = ff_set_dimensions(s->avctx, s->width, s->height);
232− if (ret < 0)
233− return ret;
262+ if (s->avctx->width != s->width || s->avctx->height != s->height) {
263+ av_frame_unref(s->last_frame);
264+ ret = ff_set_dimensions(s->avctx, s->width, s->height);
265+ if (ret < 0)
266+ return ret;
267+ }
234268
235269 tgq_calculate_qtable(s, bytestream2_get_byteu(&gbyte));
236270 bytestream2_skipu(&gbyte, 3);
@@ -238,16 +272,27 @@ static int tgq_decode_frame(AVCodecContext *avctx, AVFrame *frame, · 1 unmodified line
238272 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
239273 return ret;
240274
275+ frame->flags |= AV_FRAME_FLAG_KEY;
241276 for (y = 0; y < FFALIGN(avctx->height, 16) >> 4; y++)
242277 for (x = 0; x < FFALIGN(avctx->width, 16) >> 4; x++)
243278 if (tgq_decode_mb(s, &gbyte, frame, y, x) < 0)
244279 return AVERROR_INVALIDDATA;
245280
281+ if ((ret = av_frame_replace(s->last_frame, frame)) < 0)
282+ return ret;
283+
246284 *got_frame = 1;
247285
248286 return avpkt->size;
249287 }
250288
289+static av_cold int tgq_decode_close(AVCodecContext *avctx)
290+{
291+ TgqContext *s = avctx->priv_data;
292+ av_frame_free(&s->last_frame);
293+ return 0;
294+}
295+
251296 const FFCodec ff_eatgq_decoder = {
252297 .p.name = "eatgq",
253298 CODEC_LONG_NAME("Electronic Arts TGQ video"),
@@ -255,6 +300,7 @@ const FFCodec ff_eatgq_decoder = { · 1 unmodified line
255300 .p.id = AV_CODEC_ID_TGQ,
256301 .priv_data_size = sizeof(TgqContext),
257302 .init = tgq_decode_init,
303+ .close = tgq_decode_close,
258304 FF_CODEC_DECODE_CB(tgq_decode_frame),
259305 .p.capabilities = AV_CODEC_CAP_DR1,
260306 };

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t