Libav 0.7.1
|
00001 /* 00002 * Forward Uncompressed 00003 * 00004 * Copyright (c) 2009 Reimar Döffinger <Reimar.Doeffinger@gmx.de> 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * Libav is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with Libav; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 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 = AV_PICTURE_TYPE_I; 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; // flags? 0x80 == bottom field maybe? 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 ff_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 };