00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "avcodec.h"
00024 #include "bytestream.h"
00025 #include "libavutil/intreadwrite.h"
00026
00027 static av_cold int decode_init(AVCodecContext *avctx)
00028 {
00029 if (avctx->width & 1) {
00030 av_log(avctx, AV_LOG_ERROR, "FRWU needs even width\n");
00031 return -1;
00032 }
00033 avctx->pix_fmt = PIX_FMT_UYVY422;
00034
00035 avctx->coded_frame = avcodec_alloc_frame();
00036
00037 return 0;
00038 }
00039
00040 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
00041 AVPacket *avpkt)
00042 {
00043 int field;
00044 AVFrame *pic = avctx->coded_frame;
00045 const uint8_t *buf = avpkt->data;
00046 const uint8_t *buf_end = buf + avpkt->size;
00047
00048 if (pic->data[0])
00049 avctx->release_buffer(avctx, pic);
00050
00051 if (avpkt->size < avctx->width * 2 * avctx->height + 4 + 2*8) {
00052 av_log(avctx, AV_LOG_ERROR, "Packet is too small.\n");
00053 return -1;
00054 }
00055 if (bytestream_get_le32(&buf) != AV_RL32("FRW1")) {
00056 av_log(avctx, AV_LOG_ERROR, "incorrect marker\n");
00057 return -1;
00058 }
00059
00060 pic->reference = 0;
00061 if (avctx->get_buffer(avctx, pic) < 0)
00062 return -1;
00063
00064 pic->pict_type = FF_I_TYPE;
00065 pic->key_frame = 1;
00066 pic->interlaced_frame = 1;
00067 pic->top_field_first = 1;
00068
00069 for (field = 0; field < 2; field++) {
00070 int i;
00071 int field_h = (avctx->height + !field) >> 1;
00072 int field_size, min_field_size = avctx->width * 2 * field_h;
00073 uint8_t *dst = pic->data[0];
00074 if (buf_end - buf < 8)
00075 return -1;
00076 buf += 4;
00077 field_size = bytestream_get_le32(&buf);
00078 if (field_size < min_field_size) {
00079 av_log(avctx, AV_LOG_ERROR, "Field size %i is too small (required %i)\n", field_size, min_field_size);
00080 return -1;
00081 }
00082 if (buf_end - buf < field_size) {
00083 av_log(avctx, AV_LOG_ERROR, "Packet is too small, need %i, have %i\n", field_size, (int)(buf_end - buf));
00084 return -1;
00085 }
00086 if (field)
00087 dst += pic->linesize[0];
00088 for (i = 0; i < field_h; i++) {
00089 memcpy(dst, buf, avctx->width * 2);
00090 buf += avctx->width * 2;
00091 dst += pic->linesize[0] << 1;
00092 }
00093 buf += field_size - min_field_size;
00094 }
00095
00096 *data_size = sizeof(AVFrame);
00097 *(AVFrame*)data = *pic;
00098
00099 return avpkt->size;
00100 }
00101
00102 static av_cold int decode_close(AVCodecContext *avctx)
00103 {
00104 AVFrame *pic = avctx->coded_frame;
00105 if (pic->data[0])
00106 avctx->release_buffer(avctx, pic);
00107 av_freep(&avctx->coded_frame);
00108
00109 return 0;
00110 }
00111
00112 AVCodec frwu_decoder = {
00113 "FRWU",
00114 AVMEDIA_TYPE_VIDEO,
00115 CODEC_ID_FRWU,
00116 0,
00117 decode_init,
00118 NULL,
00119 decode_close,
00120 decode_frame,
00121 CODEC_CAP_DR1,
00122 .long_name = NULL_IF_CONFIG_SMALL("Forward Uncompressed"),
00123 };