Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * Copyright (c) 2011 Derek Buitenhuis | |
3 | * | |
4 | * This file is part of FFmpeg. | |
5 | * | |
6 | * FFmpeg is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public | |
8 | * License as published by the Free Software Foundation; | |
9 | * version 2 of the License. | |
10 | * | |
11 | * FFmpeg is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | * General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public | |
17 | * License along with FFmpeg; if not, write to the Free Software | |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | */ | |
20 | ||
21 | /** | |
22 | * @file | |
23 | * Known FOURCCs: | |
24 | * 'ULY0' (YCbCr 4:2:0), 'ULY2' (YCbCr 4:2:2), 'ULRG' (RGB), 'ULRA' (RGBA), | |
25 | * 'ULH0' (YCbCr 4:2:0 BT.709), 'ULH2' (YCbCr 4:2:2 BT.709) | |
26 | */ | |
27 | ||
28 | extern "C" { | |
29 | #include "avcodec.h" | |
30 | } | |
31 | ||
32 | #include "libutvideo.h" | |
33 | #include "get_bits.h" | |
34 | ||
35 | static av_cold int utvideo_decode_init(AVCodecContext *avctx) | |
36 | { | |
37 | UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; | |
38 | UtVideoExtra info; | |
39 | int format; | |
40 | int begin_ret; | |
41 | ||
42 | if (avctx->extradata_size != 4*4) { | |
43 | av_log(avctx, AV_LOG_ERROR, "Extradata size mismatch.\n"); | |
44 | return -1; | |
45 | } | |
46 | ||
47 | /* Read extradata */ | |
48 | info.version = AV_RL32(avctx->extradata); | |
49 | info.original_format = AV_RL32(avctx->extradata + 4); | |
50 | info.frameinfo_size = AV_RL32(avctx->extradata + 8); | |
51 | info.flags = AV_RL32(avctx->extradata + 12); | |
52 | ||
53 | /* Pick format based on FOURCC */ | |
54 | switch (avctx->codec_tag) { | |
55 | #ifdef UTV_BT709 | |
56 | case MKTAG('U', 'L', 'H', '0'): | |
57 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
58 | avctx->colorspace = AVCOL_SPC_BT709; | |
59 | format = UTVF_YV12; | |
60 | break; | |
61 | case MKTAG('U', 'L', 'H', '2'): | |
62 | avctx->pix_fmt = AV_PIX_FMT_YUYV422; | |
63 | avctx->colorspace = AVCOL_SPC_BT709; | |
64 | format = UTVF_YUY2; | |
65 | break; | |
66 | #endif | |
67 | case MKTAG('U', 'L', 'Y', '0'): | |
68 | avctx->pix_fmt = AV_PIX_FMT_YUV420P; | |
69 | format = UTVF_YV12; | |
70 | break; | |
71 | case MKTAG('U', 'L', 'Y', '2'): | |
72 | avctx->pix_fmt = AV_PIX_FMT_YUYV422; | |
73 | format = UTVF_YUY2; | |
74 | break; | |
75 | case MKTAG('U', 'L', 'R', 'G'): | |
76 | avctx->pix_fmt = AV_PIX_FMT_BGR24; | |
77 | format = UTVF_NFCC_BGR_BU; | |
78 | break; | |
79 | case MKTAG('U', 'L', 'R', 'A'): | |
80 | avctx->pix_fmt = AV_PIX_FMT_RGB32; | |
81 | format = UTVF_NFCC_BGRA_BU; | |
82 | break; | |
83 | default: | |
84 | av_log(avctx, AV_LOG_ERROR, | |
85 | "Not a Ut Video FOURCC: %X\n", avctx->codec_tag); | |
86 | return -1; | |
87 | } | |
88 | ||
89 | /* Only allocate the buffer once */ | |
90 | utv->buf_size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); | |
91 | utv->buffer = (uint8_t *)av_malloc(utv->buf_size * sizeof(uint8_t)); | |
92 | ||
93 | if (utv->buffer == NULL) { | |
94 | av_log(avctx, AV_LOG_ERROR, "Unable to allocate output buffer.\n"); | |
95 | return -1; | |
96 | } | |
97 | ||
98 | /* Allocate the output frame */ | |
99 | avctx->coded_frame = av_frame_alloc(); | |
100 | ||
101 | /* Ut Video only supports 8-bit */ | |
102 | avctx->bits_per_raw_sample = 8; | |
103 | ||
104 | /* Is it interlaced? */ | |
105 | avctx->coded_frame->interlaced_frame = info.flags & 0x800 ? 1 : 0; | |
106 | ||
107 | /* Apparently Ut Video doesn't store this info... */ | |
108 | avctx->coded_frame->top_field_first = 1; | |
109 | ||
110 | /* | |
111 | * Create a Ut Video instance. Since the function wants | |
112 | * an "interface name" string, pass it the name of the lib. | |
113 | */ | |
114 | utv->codec = CCodec::CreateInstance(UNFCC(avctx->codec_tag), "libavcodec"); | |
115 | ||
116 | /* Initialize Decoding */ | |
117 | begin_ret = utv->codec->DecodeBegin(format, avctx->width, avctx->height, | |
118 | CBGROSSWIDTH_WINDOWS, &info, sizeof(UtVideoExtra)); | |
119 | ||
120 | /* Check to see if the decoder initlized properly */ | |
121 | if (begin_ret != 0) { | |
122 | av_log(avctx, AV_LOG_ERROR, | |
123 | "Could not initialize decoder: %d\n", begin_ret); | |
124 | return -1; | |
125 | } | |
126 | ||
127 | return 0; | |
128 | } | |
129 | ||
130 | static int utvideo_decode_frame(AVCodecContext *avctx, void *data, | |
131 | int *got_frame, AVPacket *avpkt) | |
132 | { | |
133 | UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; | |
134 | AVFrame *pic = avctx->coded_frame; | |
135 | int w = avctx->width, h = avctx->height; | |
136 | ||
137 | /* Set flags */ | |
138 | pic->reference = 0; | |
139 | pic->pict_type = AV_PICTURE_TYPE_I; | |
140 | pic->key_frame = 1; | |
141 | ||
142 | /* Decode the frame */ | |
143 | utv->codec->DecodeFrame(utv->buffer, avpkt->data, true); | |
144 | ||
145 | /* Set the output data depending on the colorspace */ | |
146 | switch (avctx->pix_fmt) { | |
147 | case AV_PIX_FMT_YUV420P: | |
148 | pic->linesize[0] = w; | |
149 | pic->linesize[1] = pic->linesize[2] = w / 2; | |
150 | pic->data[0] = utv->buffer; | |
151 | pic->data[2] = utv->buffer + (w * h); | |
152 | pic->data[1] = pic->data[2] + (w * h / 4); | |
153 | break; | |
154 | case AV_PIX_FMT_YUYV422: | |
155 | pic->linesize[0] = w * 2; | |
156 | pic->data[0] = utv->buffer; | |
157 | break; | |
158 | case AV_PIX_FMT_BGR24: | |
159 | case AV_PIX_FMT_RGB32: | |
160 | /* Make the linesize negative, since Ut Video uses bottom-up BGR */ | |
161 | pic->linesize[0] = -1 * w * (avctx->pix_fmt == AV_PIX_FMT_BGR24 ? 3 : 4); | |
162 | pic->data[0] = utv->buffer + utv->buf_size + pic->linesize[0]; | |
163 | break; | |
164 | } | |
165 | ||
166 | *got_frame = 1; | |
167 | av_frame_move_ref((AVFrame*)data, pic); | |
168 | ||
169 | return avpkt->size; | |
170 | } | |
171 | ||
172 | static av_cold int utvideo_decode_close(AVCodecContext *avctx) | |
173 | { | |
174 | UtVideoContext *utv = (UtVideoContext *)avctx->priv_data; | |
175 | ||
176 | /* Free output */ | |
177 | av_frame_free(&avctx->coded_frame); | |
178 | av_freep(&utv->buffer); | |
179 | ||
180 | /* Finish decoding and clean up the instance */ | |
181 | utv->codec->DecodeEnd(); | |
182 | CCodec::DeleteInstance(utv->codec); | |
183 | ||
184 | return 0; | |
185 | } | |
186 | ||
187 | AVCodec ff_libutvideo_decoder = { | |
188 | "libutvideo", | |
189 | NULL_IF_CONFIG_SMALL("Ut Video"), | |
190 | AVMEDIA_TYPE_VIDEO, | |
191 | AV_CODEC_ID_UTVIDEO, | |
192 | 0, //capabilities | |
193 | NULL, //supported_framerates | |
194 | NULL, //pix_fmts | |
195 | NULL, //supported_samplerates | |
196 | NULL, //sample_fmts | |
197 | NULL, //channel_layouts | |
198 | 0, //max_lowres | |
199 | NULL, //priv_class | |
200 | NULL, //profiles | |
201 | sizeof(UtVideoContext), | |
202 | NULL, //next | |
203 | NULL, //init_thread_copy | |
204 | NULL, //update_thread_context | |
205 | NULL, //defaults | |
206 | NULL, //init_static_data | |
207 | utvideo_decode_init, | |
208 | NULL, //encode | |
209 | NULL, //encode2 | |
210 | utvideo_decode_frame, | |
211 | utvideo_decode_close, | |
212 | }; |