00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavutil/common.h"
00023 #include "libavutil/intreadwrite.h"
00024 #include "libavutil/imgutils.h"
00025 #include "avcodec.h"
00026 #include "internal.h"
00027
00028 typedef struct PTXContext {
00029 AVFrame picture;
00030 } PTXContext;
00031
00032 static av_cold int ptx_init(AVCodecContext *avctx) {
00033 PTXContext *s = avctx->priv_data;
00034
00035 avcodec_get_frame_defaults(&s->picture);
00036 avctx->coded_frame= &s->picture;
00037
00038 return 0;
00039 }
00040
00041 static int ptx_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
00042 AVPacket *avpkt) {
00043 const uint8_t *buf = avpkt->data;
00044 const uint8_t *buf_end = avpkt->data + avpkt->size;
00045 PTXContext * const s = avctx->priv_data;
00046 AVFrame *picture = data;
00047 AVFrame * const p = &s->picture;
00048 unsigned int offset, w, h, y, stride, bytes_per_pixel;
00049 uint8_t *ptr;
00050
00051 if (buf_end - buf < 14)
00052 return AVERROR_INVALIDDATA;
00053 offset = AV_RL16(buf);
00054 w = AV_RL16(buf+8);
00055 h = AV_RL16(buf+10);
00056 bytes_per_pixel = AV_RL16(buf+12) >> 3;
00057
00058 if (bytes_per_pixel != 2) {
00059 av_log_ask_for_sample(avctx, "Image format is not RGB15.\n");
00060 return -1;
00061 }
00062
00063 avctx->pix_fmt = AV_PIX_FMT_BGR555LE;
00064
00065 if (buf_end - buf < offset)
00066 return AVERROR_INVALIDDATA;
00067 if (offset != 0x2c)
00068 av_log_ask_for_sample(avctx, "offset != 0x2c\n");
00069
00070 buf += offset;
00071
00072 if (p->data[0])
00073 avctx->release_buffer(avctx, p);
00074
00075 if (av_image_check_size(w, h, 0, avctx))
00076 return -1;
00077 if (w != avctx->width || h != avctx->height)
00078 avcodec_set_dimensions(avctx, w, h);
00079 if (ff_get_buffer(avctx, p) < 0) {
00080 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00081 return -1;
00082 }
00083
00084 p->pict_type = AV_PICTURE_TYPE_I;
00085
00086 ptr = p->data[0];
00087 stride = p->linesize[0];
00088
00089 for (y = 0; y < h && buf_end - buf >= w * bytes_per_pixel; y++) {
00090 memcpy(ptr, buf, w*bytes_per_pixel);
00091 ptr += stride;
00092 buf += w*bytes_per_pixel;
00093 }
00094
00095 *picture = s->picture;
00096 *got_frame = 1;
00097
00098 if (y < h) {
00099 av_log(avctx, AV_LOG_WARNING, "incomplete packet\n");
00100 return avpkt->size;
00101 }
00102
00103 return offset + w*h*bytes_per_pixel;
00104 }
00105
00106 static av_cold int ptx_end(AVCodecContext *avctx) {
00107 PTXContext *s = avctx->priv_data;
00108
00109 if(s->picture.data[0])
00110 avctx->release_buffer(avctx, &s->picture);
00111
00112 return 0;
00113 }
00114
00115 AVCodec ff_ptx_decoder = {
00116 .name = "ptx",
00117 .type = AVMEDIA_TYPE_VIDEO,
00118 .id = AV_CODEC_ID_PTX,
00119 .priv_data_size = sizeof(PTXContext),
00120 .init = ptx_init,
00121 .close = ptx_end,
00122 .decode = ptx_decode_frame,
00123 .capabilities = CODEC_CAP_DR1,
00124 .long_name = NULL_IF_CONFIG_SMALL("V.Flash PTX image"),
00125 };