Libav 0.7.1
|
00001 /* 00002 * V.Flash PTX (.ptx) image decoder 00003 * Copyright (c) 2007 Ivo van Poorten 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include "libavutil/intreadwrite.h" 00023 #include "libavutil/imgutils.h" 00024 #include "avcodec.h" 00025 00026 typedef struct PTXContext { 00027 AVFrame picture; 00028 } PTXContext; 00029 00030 static av_cold int ptx_init(AVCodecContext *avctx) { 00031 PTXContext *s = avctx->priv_data; 00032 00033 avcodec_get_frame_defaults(&s->picture); 00034 avctx->coded_frame= &s->picture; 00035 00036 return 0; 00037 } 00038 00039 static int ptx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, 00040 AVPacket *avpkt) { 00041 const uint8_t *buf = avpkt->data; 00042 const uint8_t *buf_end = avpkt->data + avpkt->size; 00043 PTXContext * const s = avctx->priv_data; 00044 AVFrame *picture = data; 00045 AVFrame * const p = &s->picture; 00046 unsigned int offset, w, h, y, stride, bytes_per_pixel; 00047 uint8_t *ptr; 00048 00049 if (buf_end - buf < 14) 00050 return AVERROR_INVALIDDATA; 00051 offset = AV_RL16(buf); 00052 w = AV_RL16(buf+8); 00053 h = AV_RL16(buf+10); 00054 bytes_per_pixel = AV_RL16(buf+12) >> 3; 00055 00056 if (bytes_per_pixel != 2) { 00057 av_log_ask_for_sample(avctx, "Image format is not RGB15.\n"); 00058 return -1; 00059 } 00060 00061 avctx->pix_fmt = PIX_FMT_RGB555; 00062 00063 if (buf_end - buf < offset) 00064 return AVERROR_INVALIDDATA; 00065 if (offset != 0x2c) 00066 av_log_ask_for_sample(avctx, "offset != 0x2c\n"); 00067 00068 buf += offset; 00069 00070 if (p->data[0]) 00071 avctx->release_buffer(avctx, p); 00072 00073 if (av_image_check_size(w, h, 0, avctx)) 00074 return -1; 00075 if (w != avctx->width || h != avctx->height) 00076 avcodec_set_dimensions(avctx, w, h); 00077 if (avctx->get_buffer(avctx, p) < 0) { 00078 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00079 return -1; 00080 } 00081 00082 p->pict_type = AV_PICTURE_TYPE_I; 00083 00084 ptr = p->data[0]; 00085 stride = p->linesize[0]; 00086 00087 for (y=0; y<h; y++) { 00088 if (buf_end - buf < w * bytes_per_pixel) 00089 break; 00090 #if HAVE_BIGENDIAN 00091 unsigned int x; 00092 for (x=0; x<w*bytes_per_pixel; x+=bytes_per_pixel) 00093 AV_WN16(ptr+x, AV_RL16(buf+x)); 00094 #else 00095 memcpy(ptr, buf, w*bytes_per_pixel); 00096 #endif 00097 ptr += stride; 00098 buf += w*bytes_per_pixel; 00099 } 00100 00101 *picture = s->picture; 00102 *data_size = sizeof(AVPicture); 00103 00104 return offset + w*h*bytes_per_pixel; 00105 } 00106 00107 static av_cold int ptx_end(AVCodecContext *avctx) { 00108 PTXContext *s = avctx->priv_data; 00109 00110 if(s->picture.data[0]) 00111 avctx->release_buffer(avctx, &s->picture); 00112 00113 return 0; 00114 } 00115 00116 AVCodec ff_ptx_decoder = { 00117 "ptx", 00118 AVMEDIA_TYPE_VIDEO, 00119 CODEC_ID_PTX, 00120 sizeof(PTXContext), 00121 ptx_init, 00122 NULL, 00123 ptx_end, 00124 ptx_decode_frame, 00125 CODEC_CAP_DR1, 00126 NULL, 00127 .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"), 00128 };