]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/sgidec.c
ra288: use memcpy() to copy decoded samples to output
[ffmpeg] / libavcodec / sgidec.c
index f6ca7438ee0a2dd9793cc42cf6e498aea0757d7e..e5b3c5933c6b7109ba13a76d02d4c2224c61d716 100644 (file)
@@ -2,23 +2,24 @@
  * SGI image decoder
  * Todd Kirby <doubleshot@pacbell.net>
  *
- * 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/imgutils.h"
 #include "avcodec.h"
 #include "bytestream.h"
 #include "sgi.h"
@@ -28,6 +29,7 @@ typedef struct SgiState {
     unsigned int width;
     unsigned int height;
     unsigned int depth;
+    unsigned int bytes_per_channel;
     int linesize;
 } SgiState;
 
@@ -125,7 +127,7 @@ static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end,
 {
     int x, y, z;
     const uint8_t *ptr;
-    unsigned int offset = s->height * s->width;
+    unsigned int offset = s->height * s->width * s->bytes_per_channel;
 
     /* Test buffer size. */
     if (offset * s->depth > in_end - in_buf) {
@@ -135,9 +137,10 @@ static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end,
     for (y = s->height - 1; y >= 0; y--) {
         out_end = out_buf + (y * s->linesize);
         for (x = s->width; x > 0; x--) {
-            ptr = in_buf++;
+            ptr = in_buf += s->bytes_per_channel;
             for(z = 0; z < s->depth; z ++) {
-                bytestream_put_byte(&out_end, *ptr);
+                memcpy(out_end, ptr, s->bytes_per_channel);
+                out_end += s->bytes_per_channel;
                 ptr += offset;
             }
         }
@@ -147,13 +150,15 @@ static int read_uncompressed_sgi(unsigned char* out_buf, uint8_t* out_end,
 
 static int decode_frame(AVCodecContext *avctx,
                         void *data, int *data_size,
-                        const uint8_t *in_buf, int buf_size)
+                        AVPacket *avpkt)
 {
+    const uint8_t *in_buf = avpkt->data;
+    int buf_size = avpkt->size;
     SgiState *s = avctx->priv_data;
     AVFrame *picture = data;
     AVFrame *p = &s->picture;
     const uint8_t *in_end = in_buf + buf_size;
-    unsigned int dimension, bytes_per_channel, rle;
+    unsigned int dimension, rle;
     int ret = 0;
     uint8_t *out_buf, *out_end;
 
@@ -169,13 +174,13 @@ static int decode_frame(AVCodecContext *avctx,
     }
 
     rle = bytestream_get_byte(&in_buf);
-    bytes_per_channel = bytestream_get_byte(&in_buf);
+    s->bytes_per_channel = bytestream_get_byte(&in_buf);
     dimension = bytestream_get_be16(&in_buf);
     s->width  = bytestream_get_be16(&in_buf);
     s->height = bytestream_get_be16(&in_buf);
     s->depth  = bytestream_get_be16(&in_buf);
 
-    if (bytes_per_channel != 1) {
+    if (s->bytes_per_channel != 1 && (s->bytes_per_channel != 2 || rle)) {
         av_log(avctx, AV_LOG_ERROR, "wrong channel number\n");
         return -1;
     }
@@ -187,17 +192,17 @@ static int decode_frame(AVCodecContext *avctx,
     }
 
     if (s->depth == SGI_GRAYSCALE) {
-        avctx->pix_fmt = PIX_FMT_GRAY8;
+        avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_GRAY16BE : PIX_FMT_GRAY8;
     } else if (s->depth == SGI_RGB) {
-        avctx->pix_fmt = PIX_FMT_RGB24;
-    } else if (s->depth == SGI_RGBA) {
+        avctx->pix_fmt = s->bytes_per_channel == 2 ? PIX_FMT_RGB48BE : PIX_FMT_RGB24;
+    } else if (s->depth == SGI_RGBA && s->bytes_per_channel == 1) {
         avctx->pix_fmt = PIX_FMT_RGBA;
     } else {
         av_log(avctx, AV_LOG_ERROR, "wrong picture format\n");
         return -1;
     }
 
-    if (avcodec_check_dimensions(avctx, s->width, s->height))
+    if (av_image_check_size(s->width, s->height, 0, avctx))
         return -1;
     avcodec_set_dimensions(avctx, s->width, s->height);
 
@@ -210,7 +215,7 @@ static int decode_frame(AVCodecContext *avctx,
         return -1;
     }
 
-    p->pict_type = FF_I_TYPE;
+    p->pict_type = AV_PICTURE_TYPE_I;
     p->key_frame = 1;
     out_buf = p->data[0];
 
@@ -254,15 +259,14 @@ static av_cold int sgi_end(AVCodecContext *avctx)
     return 0;
 }
 
-AVCodec sgi_decoder = {
-    "sgi",
-    CODEC_TYPE_VIDEO,
-    CODEC_ID_SGI,
-    sizeof(SgiState),
-    sgi_init,
-    NULL,
-    sgi_end,
-    decode_frame,
+AVCodec ff_sgi_decoder = {
+    .name           = "sgi",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = CODEC_ID_SGI,
+    .priv_data_size = sizeof(SgiState),
+    .init           = sgi_init,
+    .close          = sgi_end,
+    .decode         = decode_frame,
     .long_name = NULL_IF_CONFIG_SMALL("SGI image"),
 };