00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 extern "C" {
00028 #include "avcodec.h"
00029 }
00030
00031 #include <stdlib.h>
00032 #include <utvideo/utvideo.h>
00033 #include <utvideo/Codec.h>
00034
00035 #include "get_bits.h"
00036
00037 typedef struct {
00038 uint32_t version;
00039 uint32_t original_format;
00040 uint32_t frameinfo_size;
00041 uint32_t flags;
00042 } UtVideoExtra;
00043
00044 typedef struct {
00045 CCodec *codec;
00046 unsigned int buf_size;
00047 uint8_t *output;
00048 } UtVideoContext;
00049
00050 static av_cold int utvideo_decode_init(AVCodecContext *avctx)
00051 {
00052 UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
00053 UtVideoExtra info;
00054 int format;
00055 int begin_ret;
00056
00057 if (avctx->extradata_size != 4*4) {
00058 av_log(avctx, AV_LOG_ERROR, "Extradata size mismatch.\n");
00059 return -1;
00060 }
00061
00062
00063 info.version = AV_RL32(avctx->extradata);
00064 info.original_format = AV_RL32(avctx->extradata + 4);
00065 info.frameinfo_size = AV_RL32(avctx->extradata + 8);
00066 info.flags = AV_RL32(avctx->extradata + 12);
00067
00068
00069 switch (avctx->codec_tag) {
00070 case MKTAG('U', 'L', 'Y', '0'):
00071 avctx->pix_fmt = PIX_FMT_YUV420P;
00072 format = UTVF_YV12;
00073 break;
00074 case MKTAG('U', 'L', 'Y', '2'):
00075 avctx->pix_fmt = PIX_FMT_YUYV422;
00076 format = UTVF_YUY2;
00077 break;
00078 case MKTAG('U', 'L', 'R', 'G'):
00079 avctx->pix_fmt = PIX_FMT_BGR24;
00080 format = UTVF_RGB24_WIN;
00081 break;
00082 case MKTAG('U', 'L', 'R', 'A'):
00083 avctx->pix_fmt = PIX_FMT_RGB32;
00084 format = UTVF_RGB32_WIN;
00085 break;
00086 default:
00087 av_log(avctx, AV_LOG_ERROR,
00088 "Not a Ut Video FOURCC: %X\n", avctx->codec_tag);
00089 return -1;
00090 }
00091
00092
00093 utv->buf_size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height);
00094 utv->output = (uint8_t *)av_malloc(utv->buf_size * sizeof(uint8_t));
00095
00096 if (utv->output == NULL) {
00097 av_log(avctx, AV_LOG_ERROR, "Unable to allocate output buffer.\n");
00098 return -1;
00099 }
00100
00101
00102 avctx->coded_frame = avcodec_alloc_frame();
00103
00104
00105 avctx->bits_per_raw_sample = 8;
00106
00107
00108 avctx->coded_frame->interlaced_frame = info.flags & 0x800 ? 1 : 0;
00109
00110
00111 avctx->coded_frame->top_field_first = 1;
00112
00113
00114
00115
00116
00117 utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec");
00118
00119
00120 begin_ret = utv->codec->DecodeBegin(format, avctx->width, avctx->height,
00121 CBGROSSWIDTH_WINDOWS, &info, sizeof(UtVideoExtra));
00122
00123
00124 if (begin_ret != 0) {
00125 av_log(avctx, AV_LOG_ERROR,
00126 "Could not initialize decoder: %d\n", begin_ret);
00127 return -1;
00128 }
00129
00130 return 0;
00131 }
00132
00133 static int utvideo_decode_frame(AVCodecContext *avctx, void *data,
00134 int *data_size, AVPacket *avpkt)
00135 {
00136 UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
00137 AVFrame *pic = avctx->coded_frame;
00138 int w = avctx->width, h = avctx->height;
00139
00140
00141 pic->reference = 0;
00142 pic->pict_type = AV_PICTURE_TYPE_I;
00143 pic->key_frame = 1;
00144
00145
00146 utv->codec->DecodeFrame(utv->output, avpkt->data, true);
00147
00148
00149 switch (avctx->pix_fmt) {
00150 case PIX_FMT_YUV420P:
00151 pic->linesize[0] = w;
00152 pic->linesize[1] = pic->linesize[2] = w / 2;
00153 pic->data[0] = utv->output;
00154 pic->data[2] = utv->output + (w * h);
00155 pic->data[1] = pic->data[2] + (w * h / 4);
00156 break;
00157 case PIX_FMT_YUYV422:
00158 pic->linesize[0] = w * 2;
00159 pic->data[0] = utv->output;
00160 break;
00161 case PIX_FMT_BGR24:
00162 case PIX_FMT_RGB32:
00163
00164 pic->linesize[0] = -1 * w * (avctx->pix_fmt == PIX_FMT_BGR24 ? 3 : 4);
00165 pic->data[0] = utv->output + utv->buf_size + pic->linesize[0];
00166 break;
00167 }
00168
00169 *data_size = sizeof(AVFrame);
00170 *(AVFrame *)data = *pic;
00171
00172 return avpkt->size;
00173 }
00174
00175 static av_cold int utvideo_decode_close(AVCodecContext *avctx)
00176 {
00177 UtVideoContext *utv = (UtVideoContext *)avctx->priv_data;
00178
00179
00180 av_freep(&avctx->coded_frame);
00181 av_freep(&utv->output);
00182
00183
00184 utv->codec->DecodeEnd();
00185 CCodec::DeleteInstance(utv->codec);
00186
00187 return 0;
00188 }
00189
00190 AVCodec ff_libutvideo_decoder = {
00191 "libutvideo",
00192 NULL_IF_CONFIG_SMALL("Ut Video"),
00193 AVMEDIA_TYPE_VIDEO,
00194 CODEC_ID_UTVIDEO,
00195 0,
00196 NULL,
00197 NULL,
00198 NULL,
00199 NULL,
00200 NULL,
00201 0,
00202 NULL,
00203 NULL,
00204 sizeof(UtVideoContext),
00205 NULL,
00206 NULL,
00207 NULL,
00208 NULL,
00209 NULL,
00210 utvideo_decode_init,
00211 NULL,
00212 NULL,
00213 utvideo_decode_frame,
00214 utvideo_decode_close,
00215 };