Browse code

Implement shared parsing of INFO tag in Canopus family

Add some bounds checking to CLLC; reduce HQX variable scoping,
add an error message.

Vittorio Giovara authored on 2015/04/10 01:11:10
Showing 5 changed files
... ...
@@ -156,7 +156,7 @@ OBJS-$(CONFIG_CDXL_DECODER)            += cdxl.o
156 156
 OBJS-$(CONFIG_CINEPAK_DECODER)         += cinepak.o
157 157
 OBJS-$(CONFIG_CLJR_DECODER)            += cljrdec.o
158 158
 OBJS-$(CONFIG_CLJR_ENCODER)            += cljrenc.o
159
-OBJS-$(CONFIG_CLLC_DECODER)            += cllc.o
159
+OBJS-$(CONFIG_CLLC_DECODER)            += cllc.o canopus.o
160 160
 OBJS-$(CONFIG_COOK_DECODER)            += cook.o
161 161
 OBJS-$(CONFIG_COMFORTNOISE_DECODER)    += cngdec.o celp_filters.o
162 162
 OBJS-$(CONFIG_COMFORTNOISE_ENCODER)    += cngenc.o
... ...
@@ -232,7 +232,7 @@ OBJS-$(CONFIG_HEVC_DECODER)            += hevc.o hevc_mvs.o hevc_ps.o hevc_sei.o
232 232
                                           hevc_cabac.o hevc_refs.o hevcpred.o    \
233 233
                                           hevcdsp.o hevc_filter.o
234 234
 OBJS-$(CONFIG_HNM4_VIDEO_DECODER)      += hnm4video.o
235
-OBJS-$(CONFIG_HQX_DECODER)             += hqx.o hqxvlc.o hqxdsp.o
235
+OBJS-$(CONFIG_HQX_DECODER)             += hqx.o hqxvlc.o hqxdsp.o canopus.o
236 236
 OBJS-$(CONFIG_HUFFYUV_DECODER)         += huffyuv.o huffyuvdec.o
237 237
 OBJS-$(CONFIG_HUFFYUV_ENCODER)         += huffyuv.o huffyuvenc.o
238 238
 OBJS-$(CONFIG_IDCIN_DECODER)           += idcinvideo.o
239 239
new file mode 100644
... ...
@@ -0,0 +1,63 @@
0
+/*
1
+ * Canopus common routines
2
+ * Copyright (c) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
3
+ *
4
+ * This file is part of Libav.
5
+ *
6
+ * Libav is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * Libav is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with Libav; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#include <stdint.h>
22
+
23
+#include "libavutil/rational.h"
24
+
25
+#include "avcodec.h"
26
+#include "bytestream.h"
27
+#include "canopus.h"
28
+
29
+int ff_canopus_parse_info_tag(AVCodecContext *avctx,
30
+                              const uint8_t *src, size_t size)
31
+{
32
+    GetByteContext gbc;
33
+    int par_x, par_y, field_order;
34
+
35
+    bytestream2_init(&gbc, src, size);
36
+
37
+    /* Parse aspect ratio. */
38
+    bytestream2_skip(&gbc, 8); // unknown, 16 bits 1
39
+    par_x = bytestream2_get_le32(&gbc);
40
+    par_y = bytestream2_get_le32(&gbc);
41
+    if (par_x && par_y)
42
+        av_reduce(&avctx->sample_aspect_ratio.num,
43
+                  &avctx->sample_aspect_ratio.den,
44
+                  par_x, par_y, 255);
45
+
46
+    /* Short INFO tag (used in CLLC) has only AR data. */
47
+    if (size == 0x18)
48
+        return 0;
49
+
50
+    bytestream2_skip(&gbc, 16); // unknown RDRT tag
51
+
52
+    /* Parse FIEL tag. */
53
+    bytestream2_skip(&gbc, 8); // 'FIEL' and 4 bytes 0
54
+    field_order = bytestream2_get_le32(&gbc);
55
+    switch (field_order) {
56
+    case 0: avctx->field_order = AV_FIELD_TT; break;
57
+    case 1: avctx->field_order = AV_FIELD_BB; break;
58
+    case 2: avctx->field_order = AV_FIELD_PROGRESSIVE; break;
59
+    }
60
+
61
+    return 0;
62
+}
0 63
new file mode 100644
... ...
@@ -0,0 +1,32 @@
0
+/*
1
+ * Canopus common routines
2
+ * Copyright (c) 2015 Vittorio Giovara <vittorio.giovara@gmail.com>
3
+ *
4
+ * This file is part of Libav.
5
+ *
6
+ * Libav is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2.1 of the License, or (at your option) any later version.
10
+ *
11
+ * Libav is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with Libav; if not, write to the Free Software
18
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ */
20
+
21
+#ifndef AVCODEC_CANOPUS_H
22
+#define AVCODEC_CANOPUS_H
23
+
24
+#include <stdint.h>
25
+
26
+#include "avcodec.h"
27
+
28
+int ff_canopus_parse_info_tag(AVCodecContext *avctx,
29
+                              const uint8_t *src, size_t size);
30
+
31
+#endif /* AVCODEC_CANOPUS_H */
... ...
@@ -24,6 +24,7 @@
24 24
 
25 25
 #include "libavutil/intreadwrite.h"
26 26
 #include "bswapdsp.h"
27
+#include "canopus.h"
27 28
 #include "get_bits.h"
28 29
 #include "avcodec.h"
29 30
 #include "internal.h"
... ...
@@ -362,7 +363,11 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data,
362 362
     GetBitContext gb;
363 363
     int coding_type, ret;
364 364
 
365
-    /* Skip the INFO header if present */
365
+    if (avpkt->size < 4 + 4) {
366
+        av_log(avctx, AV_LOG_ERROR, "Frame is too small %d.\n", avpkt->size);
367
+        return AVERROR_INVALIDDATA;
368
+    }
369
+
366 370
     info_offset = 0;
367 371
     info_tag    = AV_RL32(src);
368 372
     if (info_tag == MKTAG('I', 'N', 'F', 'O')) {
... ...
@@ -373,11 +378,10 @@ static int cllc_decode_frame(AVCodecContext *avctx, void *data,
373 373
                    info_offset);
374 374
             return AVERROR_INVALIDDATA;
375 375
         }
376
+        ff_canopus_parse_info_tag(avctx, src + 8, info_offset);
376 377
 
377 378
         info_offset += 8;
378 379
         src         += info_offset;
379
-
380
-        av_log(avctx, AV_LOG_DEBUG, "Skipping INFO chunk.\n");
381 380
     }
382 381
 
383 382
     data_size = (avpkt->size - info_offset) & ~1;
... ...
@@ -24,6 +24,7 @@
24 24
 #include "libavutil/intreadwrite.h"
25 25
 
26 26
 #include "avcodec.h"
27
+#include "canopus.h"
27 28
 #include "get_bits.h"
28 29
 #include "internal.h"
29 30
 
... ...
@@ -405,29 +406,28 @@ static int hqx_decode_frame(AVCodecContext *avctx, void *data,
405 405
 {
406 406
     HQXContext *ctx = avctx->priv_data;
407 407
     uint8_t *src = avpkt->data;
408
-    uint32_t info_tag, info_offset;
408
+    uint32_t info_tag;
409 409
     int data_start;
410 410
     int i, ret;
411 411
 
412
-    if (avpkt->size < 8)
412
+    if (avpkt->size < 4 + 4) {
413
+        av_log(avctx, AV_LOG_ERROR, "Frame is too small %d.\n", avpkt->size);
413 414
         return AVERROR_INVALIDDATA;
415
+    }
414 416
 
415
-    /* Skip the INFO header if present */
416
-    info_offset = 0;
417 417
     info_tag    = AV_RL32(src);
418 418
     if (info_tag == MKTAG('I', 'N', 'F', 'O')) {
419
-        info_offset = AV_RL32(src + 4);
419
+        int info_offset = AV_RL32(src + 4);
420 420
         if (info_offset > UINT32_MAX - 8 || info_offset + 8 > avpkt->size) {
421 421
             av_log(avctx, AV_LOG_ERROR,
422 422
                    "Invalid INFO header offset: 0x%08"PRIX32" is too large.\n",
423 423
                    info_offset);
424 424
             return AVERROR_INVALIDDATA;
425 425
         }
426
+        ff_canopus_parse_info_tag(avctx, src + 8, info_offset);
426 427
 
427 428
         info_offset += 8;
428 429
         src         += info_offset;
429
-
430
-        av_log(avctx, AV_LOG_DEBUG, "Skipping INFO chunk.\n");
431 430
     }
432 431
 
433 432
     data_start     = src - avpkt->data;