1/* 2 * V.Flash PTX (.ptx) image decoder 3 * Copyright (c) 2007 Ivo van Poorten 4 * 5 * This file is part of Libav. 6 * 7 * Libav is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * Libav is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "libavutil/intreadwrite.h" 23#include "libavutil/imgutils.h" 24#include "avcodec.h" 25 26typedef struct PTXContext { 27 AVFrame picture; 28} PTXContext; 29 30static av_cold int ptx_init(AVCodecContext *avctx) { 31 PTXContext *s = avctx->priv_data; 32 33 avcodec_get_frame_defaults(&s->picture); 34 avctx->coded_frame= &s->picture; 35 36 return 0; 37} 38 39static int ptx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, 40 AVPacket *avpkt) { 41 const uint8_t *buf = avpkt->data; 42 const uint8_t *buf_end = avpkt->data + avpkt->size; 43 PTXContext * const s = avctx->priv_data; 44 AVFrame *picture = data; 45 AVFrame * const p = &s->picture; 46 unsigned int offset, w, h, y, stride, bytes_per_pixel; 47 uint8_t *ptr; 48 49 if (buf_end - buf < 14) 50 return AVERROR_INVALIDDATA; 51 offset = AV_RL16(buf); 52 w = AV_RL16(buf+8); 53 h = AV_RL16(buf+10); 54 bytes_per_pixel = AV_RL16(buf+12) >> 3; 55 56 if (bytes_per_pixel != 2) { 57 av_log_ask_for_sample(avctx, "Image format is not RGB15.\n"); 58 return -1; 59 } 60 61 avctx->pix_fmt = PIX_FMT_RGB555; 62 63 if (buf_end - buf < offset) 64 return AVERROR_INVALIDDATA; 65 if (offset != 0x2c) 66 av_log_ask_for_sample(avctx, "offset != 0x2c\n"); 67 68 buf += offset; 69 70 if (p->data[0]) 71 avctx->release_buffer(avctx, p); 72 73 if (av_image_check_size(w, h, 0, avctx)) 74 return -1; 75 if (w != avctx->width || h != avctx->height) 76 avcodec_set_dimensions(avctx, w, h); 77 if (avctx->get_buffer(avctx, p) < 0) { 78 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 79 return -1; 80 } 81 82 p->pict_type = AV_PICTURE_TYPE_I; 83 84 ptr = p->data[0]; 85 stride = p->linesize[0]; 86 87 for (y = 0; y < h && buf_end - buf >= w * bytes_per_pixel; y++) { 88#if HAVE_BIGENDIAN 89 unsigned int x; 90 for (x=0; x<w*bytes_per_pixel; x+=bytes_per_pixel) 91 AV_WN16(ptr+x, AV_RL16(buf+x)); 92#else 93 memcpy(ptr, buf, w*bytes_per_pixel); 94#endif 95 ptr += stride; 96 buf += w*bytes_per_pixel; 97 } 98 99 *picture = s->picture; 100 *data_size = sizeof(AVPicture); 101 102 if (y < h) { 103 av_log(avctx, AV_LOG_WARNING, "incomplete packet\n"); 104 return avpkt->size; 105 } 106 107 return offset + w*h*bytes_per_pixel; 108} 109 110static av_cold int ptx_end(AVCodecContext *avctx) { 111 PTXContext *s = avctx->priv_data; 112 113 if(s->picture.data[0]) 114 avctx->release_buffer(avctx, &s->picture); 115 116 return 0; 117} 118 119AVCodec ff_ptx_decoder = { 120 .name = "ptx", 121 .type = AVMEDIA_TYPE_VIDEO, 122 .id = CODEC_ID_PTX, 123 .priv_data_size = sizeof(PTXContext), 124 .init = ptx_init, 125 .close = ptx_end, 126 .decode = ptx_decode_frame, 127 .capabilities = CODEC_CAP_DR1, 128 .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), 129}; 130