libfdk-aacdec: Decode the first AAC frame to reliably identify the bitstream
[ffmpeg.git] / libavcodec / txd.c
index 9c60b4c..8f12291 100644 (file)
  *
  * See also: http://wiki.multimedia.cx/index.php?title=TXD
  *
- * This file is part of FFmpeg.
+ * This file is part of Libav.
  *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "libavutil/intreadwrite.h"
+#include "libavutil/imgutils.h"
 #include "avcodec.h"
+#include "bytestream.h"
+#include "internal.h"
 #include "s3tc.h"
 
-typedef struct TXDContext {
-    AVFrame picture;
-} TXDContext;
-
-static int txd_init(AVCodecContext *avctx) {
-    TXDContext *s = avctx->priv_data;
-
-    avcodec_get_frame_defaults(&s->picture);
-    avctx->coded_frame = &s->picture;
-    s->picture.data[0] = NULL;
-
-    return 0;
-}
-
-static int txd_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
-                            uint8_t *buf, int buf_size) {
-    TXDContext * const s = avctx->priv_data;
-    AVFrame *picture = data;
-    AVFrame * const p = &s->picture;
-    unsigned int version, w, h, d3d_format, depth, stride, mipmap_count, flags;
+static int txd_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
+                            AVPacket *avpkt) {
+    GetByteContext gb;
+    AVFrame * const p = data;
+    unsigned int version, w, h, d3d_format, depth, stride, flags;
     unsigned int y, v;
-    uint8_t *ptr, *cur = buf;
-    uint32_t *palette = (uint32_t *)(cur + 88), *pal;
-
-    version         = AV_RL32(cur);
-    d3d_format      = AV_RL32(cur+76);
-    w               = AV_RL16(cur+80);
-    h               = AV_RL16(cur+82);
-    depth           = AV_RL8 (cur+84);
-    mipmap_count    = AV_RL8 (cur+85);
-    flags           = AV_RL8 (cur+87);
-    cur            += 92;
+    uint8_t *ptr;
+    uint32_t *pal;
+    int ret;
+
+    bytestream2_init(&gb, avpkt->data, avpkt->size);
+    version         = bytestream2_get_le32(&gb);
+    bytestream2_skip(&gb, 72);
+    d3d_format      = bytestream2_get_le32(&gb);
+    w               = bytestream2_get_le16(&gb);
+    h               = bytestream2_get_le16(&gb);
+    depth           = bytestream2_get_byte(&gb);
+    bytestream2_skip(&gb, 2);
+    flags           = bytestream2_get_byte(&gb);
 
     if (version < 8 || version > 9) {
         av_log(avctx, AV_LOG_ERROR, "texture data version %i is unsupported\n",
                                                                     version);
-        return -1;
+        return AVERROR_PATCHWELCOME;
     }
 
     if (depth == 8) {
-        avctx->pix_fmt = PIX_FMT_PAL8;
-        cur += 1024;
-    } else if (depth == 16 || depth == 32)
-        avctx->pix_fmt = PIX_FMT_RGB32;
-    else {
+        avctx->pix_fmt = AV_PIX_FMT_PAL8;
+    } else if (depth == 16 || depth == 32) {
+        avctx->pix_fmt = AV_PIX_FMT_RGB32;
+    } else {
         av_log(avctx, AV_LOG_ERROR, "depth of %i is unsupported\n", depth);
-        return -1;
+        return AVERROR_PATCHWELCOME;
     }
 
-    if (p->data[0])
-        avctx->release_buffer(avctx, p);
+    if ((ret = ff_set_dimensions(avctx, w, h)) < 0)
+        return ret;
 
-    if (avcodec_check_dimensions(avctx, w, h))
-        return -1;
-    if (w != avctx->width || h != avctx->height)
-        avcodec_set_dimensions(avctx, w, h);
-    if (avctx->get_buffer(avctx, p) < 0) {
+    if ((ret = ff_get_buffer(avctx, p, 0)) < 0) {
         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
-        return -1;
+        return ret;
     }
 
-    p->pict_type = FF_I_TYPE;
+    p->pict_type = AV_PICTURE_TYPE_I;
 
     ptr    = p->data[0];
     stride = p->linesize[0];
 
     if (depth == 8) {
         pal = (uint32_t *) p->data[1];
-        for (y=0; y<256; y++) {
-            v = AV_RB32(palette+y);
-            pal[y] = (v>>8) + (v<<24);
+        for (y = 0; y < 256; y++) {
+            v = bytestream2_get_be32(&gb);
+            pal[y] = (v >> 8) + (v << 24);
         }
+        bytestream2_skip(&gb, 4);
         for (y=0; y<h; y++) {
-            memcpy(ptr, cur, w);
+            bytestream2_get_buffer(&gb, ptr, w);
             ptr += stride;
-            cur += w;
         }
     } else if (depth == 16) {
+        bytestream2_skip(&gb, 4);
         switch (d3d_format) {
         case 0:
-            if (!flags&1) goto unsupported;
+            if (!(flags & 1))
+                goto unsupported;
         case FF_S3TC_DXT1:
-            ff_decode_dxt1(cur, ptr, w, h, stride);
+            ff_decode_dxt1(&gb, ptr, w, h, stride);
             break;
         case FF_S3TC_DXT3:
-            ff_decode_dxt3(cur, ptr, w, h, stride);
+            ff_decode_dxt3(&gb, ptr, w, h, stride);
             break;
         default:
             goto unsupported;
@@ -119,9 +107,8 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
         case 0x15:
         case 0x16:
             for (y=0; y<h; y++) {
-                memcpy(ptr, cur, w*4);
+                bytestream2_get_buffer(&gb, ptr, w * 4);
                 ptr += stride;
-                cur += w*4;
             }
             break;
         default:
@@ -129,37 +116,20 @@ static int txd_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
         }
     }
 
-    for (; mipmap_count > 1; mipmap_count--)
-        cur += AV_RL32(cur) + 4;
+    *got_frame = 1;
 
-    *picture   = s->picture;
-    *data_size = sizeof(AVPicture);
-
-    return cur - buf;
+    return avpkt->size;
 
 unsupported:
     av_log(avctx, AV_LOG_ERROR, "unsupported d3d format (%08x)\n", d3d_format);
-    return -1;
-}
-
-static int txd_end(AVCodecContext *avctx) {
-    TXDContext *s = avctx->priv_data;
-
-    if (s->picture.data[0])
-        avctx->release_buffer(avctx, &s->picture);
-
-    return 0;
+    return AVERROR_PATCHWELCOME;
 }
 
-AVCodec txd_decoder = {
-    "txd",
-    CODEC_TYPE_VIDEO,
-    CODEC_ID_TXD,
-    sizeof(TXDContext),
-    txd_init,
-    NULL,
-    txd_end,
-    txd_decode_frame,
-    0,
-    NULL
+AVCodec ff_txd_decoder = {
+    .name           = "txd",
+    .long_name      = NULL_IF_CONFIG_SMALL("Renderware TXD (TeXture Dictionary) image"),
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = AV_CODEC_ID_TXD,
+    .decode         = txd_decode_frame,
+    .capabilities   = CODEC_CAP_DR1,
 };