Mercurial > libavcodec.hg
annotate libdiracenc.c @ 9859:7a116de63777 libavcodec
idct_dc for VC-1/WMV3 decoder; ~11% faster decoding overall.
Includes mmx2 asm for the various functions.
Note that the actual idct still does not have an x86 SIMD implemtation.
For wmv3 files using regular idct, the decoder just falls back to simple_idct,
since simple_idct_dc doesn't exist (yet).
author | darkshikari |
---|---|
date | Tue, 16 Jun 2009 09:00:55 +0000 |
parents | 043574c5c153 |
children | fdb318d12314 |
rev | line source |
---|---|
6734 | 1 /* |
2 * Dirac encoding support via libdirac library | |
3 * Copyright (c) 2005 BBC, Andrew Kennedy <dirac at rd dot bbc dot co dot uk> | |
4 * Copyright (c) 2006-2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com > | |
5 * | |
6 * This file is part of FFmpeg. | |
7 * | |
8 * FFmpeg is free software; you can redistribute it and/or | |
9 * modify it under the terms of the GNU Lesser General Public | |
10 * License as published by the Free Software Foundation; either | |
11 * version 2.1 of the License, or (at your option) any later version. | |
12 * | |
13 * FFmpeg is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
16 * Lesser General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU Lesser General Public | |
19 * License along with FFmpeg; if not, write to the Free Software | |
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
21 */ | |
22 | |
23 /** | |
8718
e9d9d946f213
Use full internal pathname in doxygen @file directives.
diego
parents:
8021
diff
changeset
|
24 * @file libavcodec/libdiracenc.c |
6734 | 25 * Dirac encoding support via libdirac library; more details about the |
26 * Dirac project can be found at http://dirac.sourceforge.net/. | |
27 * The libdirac_encoder library implements Dirac specification version 2.2 | |
28 * (http://dirac.sourceforge.net/specification.html). | |
29 */ | |
30 | |
31 #include "libdirac_libschro.h" | |
32 #include "libdirac.h" | |
33 | |
34 #undef NDEBUG | |
35 #include <assert.h> | |
36 | |
37 | |
38 #include <libdirac_encoder/dirac_encoder.h> | |
39 | |
40 /** Dirac encoder private data */ | |
41 typedef struct FfmpegDiracEncoderParams | |
42 { | |
43 /** Dirac encoder context */ | |
44 dirac_encoder_context_t enc_ctx; | |
45 | |
46 /** frame being encoded */ | |
47 AVFrame picture; | |
48 | |
49 /** frame size */ | |
50 int frame_size; | |
51 | |
52 /** Dirac encoder handle */ | |
53 dirac_encoder_t* p_encoder; | |
54 | |
55 /** input frame buffer */ | |
56 unsigned char *p_in_frame_buf; | |
57 | |
7252 | 58 /** buffer to store encoder output before writing it to the frame queue */ |
59 unsigned char *enc_buf; | |
60 | |
61 /** size of encoder buffer */ | |
62 int enc_buf_size; | |
63 | |
6734 | 64 /** queue storing encoded frames */ |
65 FfmpegDiracSchroQueue enc_frame_queue; | |
66 | |
67 /** end of sequence signalled by user, 0 - false, 1 - true */ | |
68 int eos_signalled; | |
69 | |
70 /** end of sequence returned by encoder, 0 - false, 1 - true */ | |
71 int eos_pulled; | |
72 } FfmpegDiracEncoderParams; | |
73 | |
74 /** | |
75 * Works out Dirac-compatible chroma format. | |
76 */ | |
77 static dirac_chroma_t GetDiracChromaFormat(enum PixelFormat ff_pix_fmt) | |
78 { | |
79 int num_formats = sizeof(ffmpeg_dirac_pixel_format_map) / | |
80 sizeof(ffmpeg_dirac_pixel_format_map[0]); | |
81 int idx; | |
82 | |
83 for (idx = 0; idx < num_formats; ++idx) { | |
84 if (ffmpeg_dirac_pixel_format_map[idx].ff_pix_fmt == ff_pix_fmt) { | |
85 return ffmpeg_dirac_pixel_format_map[idx].dirac_pix_fmt; | |
86 } | |
87 } | |
88 return formatNK; | |
89 } | |
90 | |
91 /** | |
92 * Dirac video preset table. Ensure that this tables matches up correctly | |
93 * with the ff_dirac_schro_video_format_info table in libdirac_libschro.c. | |
94 */ | |
95 static const VideoFormat ff_dirac_video_formats[]={ | |
96 VIDEO_FORMAT_CUSTOM , | |
97 VIDEO_FORMAT_QSIF525 , | |
98 VIDEO_FORMAT_QCIF , | |
99 VIDEO_FORMAT_SIF525 , | |
100 VIDEO_FORMAT_CIF , | |
101 VIDEO_FORMAT_4SIF525 , | |
102 VIDEO_FORMAT_4CIF , | |
103 VIDEO_FORMAT_SD_480I60 , | |
104 VIDEO_FORMAT_SD_576I50 , | |
105 VIDEO_FORMAT_HD_720P60 , | |
106 VIDEO_FORMAT_HD_720P50 , | |
107 VIDEO_FORMAT_HD_1080I60 , | |
108 VIDEO_FORMAT_HD_1080I50 , | |
109 VIDEO_FORMAT_HD_1080P60 , | |
110 VIDEO_FORMAT_HD_1080P50 , | |
111 VIDEO_FORMAT_DIGI_CINEMA_2K24 , | |
112 VIDEO_FORMAT_DIGI_CINEMA_4K24 , | |
113 }; | |
114 | |
115 /** | |
116 * Returns the video format preset matching the input video dimensions and | |
117 * time base. | |
118 */ | |
119 static VideoFormat GetDiracVideoFormatPreset (AVCodecContext *avccontext) | |
120 { | |
121 unsigned int num_formats = sizeof(ff_dirac_video_formats) / | |
122 sizeof(ff_dirac_video_formats[0]); | |
123 | |
124 unsigned int idx = ff_dirac_schro_get_video_format_idx (avccontext); | |
125 | |
126 return (idx < num_formats) ? | |
127 ff_dirac_video_formats[idx] : VIDEO_FORMAT_CUSTOM; | |
128 } | |
129 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8718
diff
changeset
|
130 static av_cold int libdirac_encode_init(AVCodecContext *avccontext) |
6734 | 131 { |
132 | |
133 FfmpegDiracEncoderParams* p_dirac_params = avccontext->priv_data; | |
134 int no_local = 1; | |
135 int verbose = avccontext->debug; | |
136 VideoFormat preset; | |
137 | |
138 /* get Dirac preset */ | |
139 preset = GetDiracVideoFormatPreset(avccontext); | |
140 | |
141 /* initialize the encoder context */ | |
142 dirac_encoder_context_init (&(p_dirac_params->enc_ctx), preset); | |
143 | |
144 p_dirac_params->enc_ctx.src_params.chroma = | |
145 GetDiracChromaFormat(avccontext->pix_fmt); | |
146 | |
147 if (p_dirac_params->enc_ctx.src_params.chroma == formatNK) { | |
148 av_log (avccontext, AV_LOG_ERROR, | |
149 "Unsupported pixel format %d. This codec supports only " | |
150 "Planar YUV formats (yuv420p, yuv422p, yuv444p\n", | |
151 avccontext->pix_fmt); | |
152 return -1; | |
153 } | |
154 | |
155 p_dirac_params->enc_ctx.src_params.frame_rate.numerator = | |
156 avccontext->time_base.den; | |
157 p_dirac_params->enc_ctx.src_params.frame_rate.denominator = | |
158 avccontext->time_base.num; | |
159 | |
160 p_dirac_params->enc_ctx.src_params.width = avccontext->width; | |
161 p_dirac_params->enc_ctx.src_params.height = avccontext->height; | |
162 | |
163 p_dirac_params->frame_size = avpicture_get_size(avccontext->pix_fmt, | |
164 avccontext->width, | |
165 avccontext->height); | |
166 | |
167 avccontext->coded_frame = &p_dirac_params->picture; | |
168 | |
169 if (no_local) { | |
170 p_dirac_params->enc_ctx.decode_flag = 0; | |
171 p_dirac_params->enc_ctx.instr_flag = 0; | |
172 } else { | |
173 p_dirac_params->enc_ctx.decode_flag = 1; | |
174 p_dirac_params->enc_ctx.instr_flag = 1; | |
175 } | |
176 | |
177 /* Intra-only sequence */ | |
7839
e6348a5656e0
Add support for creating Simple Profile (I-frame only, no arithmetic coding)
diego
parents:
7252
diff
changeset
|
178 if (avccontext->gop_size == 0 ) { |
6734 | 179 p_dirac_params->enc_ctx.enc_params.num_L1 = 0; |
7839
e6348a5656e0
Add support for creating Simple Profile (I-frame only, no arithmetic coding)
diego
parents:
7252
diff
changeset
|
180 if (avccontext->coder_type == FF_CODER_TYPE_VLC) |
e6348a5656e0
Add support for creating Simple Profile (I-frame only, no arithmetic coding)
diego
parents:
7252
diff
changeset
|
181 p_dirac_params->enc_ctx.enc_params.using_ac = 0; |
e6348a5656e0
Add support for creating Simple Profile (I-frame only, no arithmetic coding)
diego
parents:
7252
diff
changeset
|
182 } else |
6734 | 183 avccontext->has_b_frames = 1; |
184 | |
185 if (avccontext->flags & CODEC_FLAG_QSCALE) { | |
186 if (avccontext->global_quality != 0) { | |
187 p_dirac_params->enc_ctx.enc_params.qf = | |
188 avccontext->global_quality / (FF_QP2LAMBDA*10.0); | |
189 /* if it is not default bitrate then send target rate. */ | |
190 if (avccontext->bit_rate >= 1000 && | |
191 avccontext->bit_rate != 200000) { | |
192 p_dirac_params->enc_ctx.enc_params.trate = | |
193 avccontext->bit_rate / 1000; | |
194 } | |
195 } else | |
196 p_dirac_params->enc_ctx.enc_params.lossless = 1; | |
197 } else if (avccontext->bit_rate >= 1000) | |
198 p_dirac_params->enc_ctx.enc_params.trate = avccontext->bit_rate / 1000; | |
199 | |
200 if ((preset > VIDEO_FORMAT_QCIF || preset < VIDEO_FORMAT_QSIF525) && | |
201 avccontext->bit_rate == 200000) { | |
202 p_dirac_params->enc_ctx.enc_params.trate = 0; | |
203 } | |
204 | |
205 if (avccontext->flags & CODEC_FLAG_INTERLACED_ME) { | |
206 /* all material can be coded as interlaced or progressive | |
207 * irrespective of the type of source material */ | |
208 p_dirac_params->enc_ctx.enc_params.picture_coding_mode = 1; | |
209 } | |
210 | |
211 p_dirac_params->p_encoder = dirac_encoder_init (&(p_dirac_params->enc_ctx), | |
212 verbose ); | |
213 | |
214 if (!p_dirac_params->p_encoder) { | |
215 av_log(avccontext, AV_LOG_ERROR, | |
216 "Unrecoverable Error: dirac_encoder_init failed. "); | |
217 return EXIT_FAILURE; | |
218 } | |
219 | |
220 /* allocate enough memory for the incoming data */ | |
221 p_dirac_params->p_in_frame_buf = av_malloc(p_dirac_params->frame_size); | |
222 | |
223 /* initialize the encoded frame queue */ | |
224 ff_dirac_schro_queue_init(&p_dirac_params->enc_frame_queue); | |
225 | |
226 return 0 ; | |
227 } | |
228 | |
229 static void DiracFreeFrame (void *data) | |
230 { | |
231 FfmpegDiracSchroEncodedFrame *enc_frame = data; | |
232 | |
233 av_freep (&(enc_frame->p_encbuf)); | |
234 av_free(enc_frame); | |
235 } | |
236 | |
237 static int libdirac_encode_frame(AVCodecContext *avccontext, | |
238 unsigned char *frame, | |
239 int buf_size, void *data) | |
240 { | |
241 int enc_size = 0; | |
242 dirac_encoder_state_t state; | |
243 FfmpegDiracEncoderParams* p_dirac_params = avccontext->priv_data; | |
244 FfmpegDiracSchroEncodedFrame* p_frame_output = NULL; | |
245 FfmpegDiracSchroEncodedFrame* p_next_output_frame = NULL; | |
246 int go = 1; | |
7252 | 247 int last_frame_in_sequence = 0; |
6734 | 248 |
249 if (data == NULL) { | |
250 /* push end of sequence if not already signalled */ | |
251 if (!p_dirac_params->eos_signalled) { | |
252 dirac_encoder_end_sequence( p_dirac_params->p_encoder ); | |
253 p_dirac_params->eos_signalled = 1; | |
254 } | |
255 } else { | |
256 | |
257 /* Allocate frame data to Dirac input buffer. | |
258 * Input line size may differ from what the codec supports, | |
259 * especially when transcoding from one format to another. | |
260 * So use avpicture_layout to copy the frame. */ | |
261 avpicture_layout ((AVPicture *)data, avccontext->pix_fmt, | |
262 avccontext->width, avccontext->height, | |
263 p_dirac_params->p_in_frame_buf, | |
264 p_dirac_params->frame_size); | |
265 | |
266 /* load next frame */ | |
267 if (dirac_encoder_load (p_dirac_params->p_encoder, | |
268 p_dirac_params->p_in_frame_buf, | |
269 p_dirac_params->frame_size ) < 0) { | |
270 av_log(avccontext, AV_LOG_ERROR, "Unrecoverable Encoder Error." | |
271 " dirac_encoder_load failed...\n"); | |
272 return -1; | |
273 } | |
274 } | |
275 | |
276 if (p_dirac_params->eos_pulled) | |
277 go = 0; | |
278 | |
279 while(go) { | |
280 p_dirac_params->p_encoder->enc_buf.buffer = frame; | |
281 p_dirac_params->p_encoder->enc_buf.size = buf_size; | |
282 /* process frame */ | |
283 state = dirac_encoder_output ( p_dirac_params->p_encoder ); | |
284 | |
285 switch (state) | |
286 { | |
287 case ENC_STATE_AVAIL: | |
288 case ENC_STATE_EOS: | |
289 assert (p_dirac_params->p_encoder->enc_buf.size > 0); | |
7252 | 290 |
291 /* All non-frame data is prepended to actual frame data to | |
292 * be able to set the pts correctly. So we don't write data | |
293 * to the frame output queue until we actually have a frame | |
294 */ | |
295 | |
296 p_dirac_params->enc_buf = av_realloc ( | |
297 p_dirac_params->enc_buf, | |
298 p_dirac_params->enc_buf_size + | |
299 p_dirac_params->p_encoder->enc_buf.size | |
300 ); | |
301 memcpy(p_dirac_params->enc_buf + p_dirac_params->enc_buf_size, | |
302 p_dirac_params->p_encoder->enc_buf.buffer, | |
303 p_dirac_params->p_encoder->enc_buf.size); | |
304 | |
305 p_dirac_params->enc_buf_size += | |
306 p_dirac_params->p_encoder->enc_buf.size; | |
307 | |
308 if (state == ENC_STATE_EOS) { | |
309 p_dirac_params->eos_pulled = 1; | |
310 go = 0; | |
311 } | |
312 | |
313 /* If non-frame data, don't output it until it we get an | |
314 * encoded frame back from the encoder. */ | |
315 if (p_dirac_params->p_encoder->enc_pparams.pnum == -1) | |
316 break; | |
317 | |
6734 | 318 /* create output frame */ |
319 p_frame_output = av_mallocz(sizeof(FfmpegDiracSchroEncodedFrame)); | |
320 /* set output data */ | |
7252 | 321 p_frame_output->size = p_dirac_params->enc_buf_size; |
322 p_frame_output->p_encbuf = p_dirac_params->enc_buf; | |
6734 | 323 p_frame_output->frame_num = |
324 p_dirac_params->p_encoder->enc_pparams.pnum; | |
325 | |
326 if (p_dirac_params->p_encoder->enc_pparams.ptype == INTRA_PICTURE && | |
327 p_dirac_params->p_encoder->enc_pparams.rtype == REFERENCE_PICTURE) | |
328 p_frame_output->key_frame = 1; | |
329 | |
330 ff_dirac_schro_queue_push_back (&p_dirac_params->enc_frame_queue, | |
331 p_frame_output); | |
332 | |
7252 | 333 p_dirac_params->enc_buf_size = 0; |
334 p_dirac_params->enc_buf = NULL; | |
6734 | 335 break; |
336 | |
337 case ENC_STATE_BUFFER: | |
338 go = 0; | |
339 break; | |
340 | |
341 case ENC_STATE_INVALID: | |
342 av_log(avccontext, AV_LOG_ERROR, | |
343 "Unrecoverable Dirac Encoder Error. Quitting...\n"); | |
344 return -1; | |
345 | |
346 default: | |
347 av_log(avccontext, AV_LOG_ERROR, "Unknown Dirac Encoder state\n"); | |
348 return -1; | |
349 } | |
350 } | |
351 | |
352 /* copy 'next' frame in queue */ | |
7252 | 353 |
354 if (p_dirac_params->enc_frame_queue.size == 1 && | |
355 p_dirac_params->eos_pulled) | |
356 last_frame_in_sequence = 1; | |
357 | |
6734 | 358 p_next_output_frame = |
359 ff_dirac_schro_queue_pop(&p_dirac_params->enc_frame_queue); | |
360 | |
361 if (p_next_output_frame == NULL) | |
362 return 0; | |
363 | |
364 memcpy(frame, p_next_output_frame->p_encbuf, p_next_output_frame->size); | |
365 avccontext->coded_frame->key_frame = p_next_output_frame->key_frame; | |
366 /* Use the frame number of the encoded frame as the pts. It is OK to do | |
367 * so since Dirac is a constant framerate codec. It expects input to be | |
368 * of constant framerate. */ | |
369 avccontext->coded_frame->pts = p_next_output_frame->frame_num; | |
370 enc_size = p_next_output_frame->size; | |
371 | |
7252 | 372 /* Append the end of sequence information to the last frame in the |
373 * sequence. */ | |
374 if (last_frame_in_sequence && p_dirac_params->enc_buf_size > 0) | |
375 { | |
376 memcpy (frame + enc_size, p_dirac_params->enc_buf, | |
377 p_dirac_params->enc_buf_size); | |
378 enc_size += p_dirac_params->enc_buf_size; | |
379 av_freep (&p_dirac_params->enc_buf); | |
380 p_dirac_params->enc_buf_size = 0; | |
381 } | |
382 | |
6734 | 383 /* free frame */ |
384 DiracFreeFrame(p_next_output_frame); | |
385 | |
386 return enc_size; | |
387 } | |
388 | |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8718
diff
changeset
|
389 static av_cold int libdirac_encode_close(AVCodecContext *avccontext) |
6734 | 390 { |
391 FfmpegDiracEncoderParams* p_dirac_params = avccontext->priv_data; | |
392 | |
393 /* close the encoder */ | |
394 dirac_encoder_close(p_dirac_params->p_encoder ); | |
395 | |
396 /* free data in the output frame queue */ | |
397 ff_dirac_schro_queue_free(&p_dirac_params->enc_frame_queue, | |
398 DiracFreeFrame); | |
399 | |
7252 | 400 /* free the encoder buffer */ |
401 if (p_dirac_params->enc_buf_size) | |
402 av_freep(&p_dirac_params->enc_buf); | |
403 | |
6734 | 404 /* free the input frame buffer */ |
405 av_freep(&p_dirac_params->p_in_frame_buf); | |
406 | |
407 return 0 ; | |
408 } | |
409 | |
410 | |
411 AVCodec libdirac_encoder = { | |
412 "libdirac", | |
413 CODEC_TYPE_VIDEO, | |
414 CODEC_ID_DIRAC, | |
415 sizeof(FfmpegDiracEncoderParams), | |
416 libdirac_encode_init, | |
417 libdirac_encode_frame, | |
418 libdirac_encode_close, | |
419 .capabilities= CODEC_CAP_DELAY, | |
8021
00fca5d6f0d9
Use PIX_FMT_NONE instead of -1 in AVCodec.pix_fmts.
cehoyos
parents:
7839
diff
changeset
|
420 .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV420P, PIX_FMT_YUV422P, PIX_FMT_YUV444P, PIX_FMT_NONE}, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6819
diff
changeset
|
421 .long_name= NULL_IF_CONFIG_SMALL("libdirac Dirac 2.2"), |
6734 | 422 } ; |