annotate ffmpeg/libavcodec/cyuv.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Creative YUV (CYUV) Video Decoder
yading@10 3 * by Mike Melanson (melanson@pcisys.net)
yading@10 4 * based on "Creative YUV (CYUV) stream format for AVI":
yading@10 5 * http://www.csse.monash.edu.au/~timf/videocodec/cyuv.txt
yading@10 6 *
yading@10 7 * Copyright (C) 2003 the ffmpeg project
yading@10 8 *
yading@10 9 * This file is part of FFmpeg.
yading@10 10 *
yading@10 11 * FFmpeg is free software; you can redistribute it and/or
yading@10 12 * modify it under the terms of the GNU Lesser General Public
yading@10 13 * License as published by the Free Software Foundation; either
yading@10 14 * version 2.1 of the License, or (at your option) any later version.
yading@10 15 *
yading@10 16 * FFmpeg is distributed in the hope that it will be useful,
yading@10 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 19 * Lesser General Public License for more details.
yading@10 20 *
yading@10 21 * You should have received a copy of the GNU Lesser General Public
yading@10 22 * License along with FFmpeg; if not, write to the Free Software
yading@10 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 24 */
yading@10 25
yading@10 26 /**
yading@10 27 * @file
yading@10 28 * Creative YUV (CYUV) Video Decoder.
yading@10 29 */
yading@10 30
yading@10 31 #include <stdio.h>
yading@10 32 #include <stdlib.h>
yading@10 33 #include <string.h>
yading@10 34
yading@10 35 #include "avcodec.h"
yading@10 36 #include "internal.h"
yading@10 37 #include "libavutil/internal.h"
yading@10 38
yading@10 39
yading@10 40 typedef struct CyuvDecodeContext {
yading@10 41 AVCodecContext *avctx;
yading@10 42 int width, height;
yading@10 43 } CyuvDecodeContext;
yading@10 44
yading@10 45 static av_cold int cyuv_decode_init(AVCodecContext *avctx)
yading@10 46 {
yading@10 47 CyuvDecodeContext *s = avctx->priv_data;
yading@10 48
yading@10 49 s->avctx = avctx;
yading@10 50 s->width = avctx->width;
yading@10 51 /* width needs to be divisible by 4 for this codec to work */
yading@10 52 if (s->width & 0x3)
yading@10 53 return AVERROR_INVALIDDATA;
yading@10 54 s->height = avctx->height;
yading@10 55
yading@10 56 return 0;
yading@10 57 }
yading@10 58
yading@10 59 static int cyuv_decode_frame(AVCodecContext *avctx,
yading@10 60 void *data, int *got_frame,
yading@10 61 AVPacket *avpkt)
yading@10 62 {
yading@10 63 const uint8_t *buf = avpkt->data;
yading@10 64 int buf_size = avpkt->size;
yading@10 65 CyuvDecodeContext *s=avctx->priv_data;
yading@10 66 AVFrame *frame = data;
yading@10 67
yading@10 68 unsigned char *y_plane;
yading@10 69 unsigned char *u_plane;
yading@10 70 unsigned char *v_plane;
yading@10 71 int y_ptr;
yading@10 72 int u_ptr;
yading@10 73 int v_ptr;
yading@10 74
yading@10 75 /* prediction error tables (make it clear that they are signed values) */
yading@10 76 const signed char *y_table = (const signed char*)buf + 0;
yading@10 77 const signed char *u_table = (const signed char*)buf + 16;
yading@10 78 const signed char *v_table = (const signed char*)buf + 32;
yading@10 79
yading@10 80 unsigned char y_pred, u_pred, v_pred;
yading@10 81 int stream_ptr;
yading@10 82 unsigned char cur_byte;
yading@10 83 int pixel_groups;
yading@10 84 int rawsize = s->height * FFALIGN(s->width,2) * 2;
yading@10 85 int ret;
yading@10 86
yading@10 87 if (avctx->codec_id == AV_CODEC_ID_AURA) {
yading@10 88 y_table = u_table;
yading@10 89 u_table = v_table;
yading@10 90 }
yading@10 91 /* sanity check the buffer size: A buffer has 3x16-bytes tables
yading@10 92 * followed by (height) lines each with 3 bytes to represent groups
yading@10 93 * of 4 pixels. Thus, the total size of the buffer ought to be:
yading@10 94 * (3 * 16) + height * (width * 3 / 4) */
yading@10 95 if (buf_size == 48 + s->height * (s->width * 3 / 4)) {
yading@10 96 avctx->pix_fmt = AV_PIX_FMT_YUV411P;
yading@10 97 } else if(buf_size == rawsize ) {
yading@10 98 avctx->pix_fmt = AV_PIX_FMT_UYVY422;
yading@10 99 } else {
yading@10 100 av_log(avctx, AV_LOG_ERROR, "got a buffer with %d bytes when %d were expected\n",
yading@10 101 buf_size, 48 + s->height * (s->width * 3 / 4));
yading@10 102 return AVERROR_INVALIDDATA;
yading@10 103 }
yading@10 104
yading@10 105 /* pixel data starts 48 bytes in, after 3x16-byte tables */
yading@10 106 stream_ptr = 48;
yading@10 107
yading@10 108 if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
yading@10 109 return ret;
yading@10 110
yading@10 111 y_plane = frame->data[0];
yading@10 112 u_plane = frame->data[1];
yading@10 113 v_plane = frame->data[2];
yading@10 114
yading@10 115 if (buf_size == rawsize) {
yading@10 116 int linesize = FFALIGN(s->width,2) * 2;
yading@10 117 y_plane += frame->linesize[0] * s->height;
yading@10 118 for (stream_ptr = 0; stream_ptr < rawsize; stream_ptr += linesize) {
yading@10 119 y_plane -= frame->linesize[0];
yading@10 120 memcpy(y_plane, buf+stream_ptr, linesize);
yading@10 121 }
yading@10 122 } else {
yading@10 123
yading@10 124 /* iterate through each line in the height */
yading@10 125 for (y_ptr = 0, u_ptr = 0, v_ptr = 0;
yading@10 126 y_ptr < (s->height * frame->linesize[0]);
yading@10 127 y_ptr += frame->linesize[0] - s->width,
yading@10 128 u_ptr += frame->linesize[1] - s->width / 4,
yading@10 129 v_ptr += frame->linesize[2] - s->width / 4) {
yading@10 130
yading@10 131 /* reset predictors */
yading@10 132 cur_byte = buf[stream_ptr++];
yading@10 133 u_plane[u_ptr++] = u_pred = cur_byte & 0xF0;
yading@10 134 y_plane[y_ptr++] = y_pred = (cur_byte & 0x0F) << 4;
yading@10 135
yading@10 136 cur_byte = buf[stream_ptr++];
yading@10 137 v_plane[v_ptr++] = v_pred = cur_byte & 0xF0;
yading@10 138 y_pred += y_table[cur_byte & 0x0F];
yading@10 139 y_plane[y_ptr++] = y_pred;
yading@10 140
yading@10 141 cur_byte = buf[stream_ptr++];
yading@10 142 y_pred += y_table[cur_byte & 0x0F];
yading@10 143 y_plane[y_ptr++] = y_pred;
yading@10 144 y_pred += y_table[(cur_byte & 0xF0) >> 4];
yading@10 145 y_plane[y_ptr++] = y_pred;
yading@10 146
yading@10 147 /* iterate through the remaining pixel groups (4 pixels/group) */
yading@10 148 pixel_groups = s->width / 4 - 1;
yading@10 149 while (pixel_groups--) {
yading@10 150
yading@10 151 cur_byte = buf[stream_ptr++];
yading@10 152 u_pred += u_table[(cur_byte & 0xF0) >> 4];
yading@10 153 u_plane[u_ptr++] = u_pred;
yading@10 154 y_pred += y_table[cur_byte & 0x0F];
yading@10 155 y_plane[y_ptr++] = y_pred;
yading@10 156
yading@10 157 cur_byte = buf[stream_ptr++];
yading@10 158 v_pred += v_table[(cur_byte & 0xF0) >> 4];
yading@10 159 v_plane[v_ptr++] = v_pred;
yading@10 160 y_pred += y_table[cur_byte & 0x0F];
yading@10 161 y_plane[y_ptr++] = y_pred;
yading@10 162
yading@10 163 cur_byte = buf[stream_ptr++];
yading@10 164 y_pred += y_table[cur_byte & 0x0F];
yading@10 165 y_plane[y_ptr++] = y_pred;
yading@10 166 y_pred += y_table[(cur_byte & 0xF0) >> 4];
yading@10 167 y_plane[y_ptr++] = y_pred;
yading@10 168
yading@10 169 }
yading@10 170 }
yading@10 171 }
yading@10 172
yading@10 173 *got_frame = 1;
yading@10 174
yading@10 175 return buf_size;
yading@10 176 }
yading@10 177
yading@10 178 #if CONFIG_AURA_DECODER
yading@10 179 AVCodec ff_aura_decoder = {
yading@10 180 .name = "aura",
yading@10 181 .type = AVMEDIA_TYPE_VIDEO,
yading@10 182 .id = AV_CODEC_ID_AURA,
yading@10 183 .priv_data_size = sizeof(CyuvDecodeContext),
yading@10 184 .init = cyuv_decode_init,
yading@10 185 .decode = cyuv_decode_frame,
yading@10 186 .capabilities = CODEC_CAP_DR1,
yading@10 187 .long_name = NULL_IF_CONFIG_SMALL("Auravision AURA"),
yading@10 188 };
yading@10 189 #endif
yading@10 190
yading@10 191 #if CONFIG_CYUV_DECODER
yading@10 192 AVCodec ff_cyuv_decoder = {
yading@10 193 .name = "cyuv",
yading@10 194 .type = AVMEDIA_TYPE_VIDEO,
yading@10 195 .id = AV_CODEC_ID_CYUV,
yading@10 196 .priv_data_size = sizeof(CyuvDecodeContext),
yading@10 197 .init = cyuv_decode_init,
yading@10 198 .decode = cyuv_decode_frame,
yading@10 199 .capabilities = CODEC_CAP_DR1,
yading@10 200 .long_name = NULL_IF_CONFIG_SMALL("Creative YUV (CYUV)"),
yading@10 201 };
yading@10 202 #endif