Mercurial > libavcodec.hg
annotate libschroedingerdec.c @ 8228:416ffc3907bf libavcodec
Remove ineffectual hack that attempts to build ppc/check_altivec.o without
AltiVec flags. The flags are set by configure and used to compile all files
anyway. Setting extra AltiVec options here just duplicates them for the files
for which they are set.
author | diego |
---|---|
date | Sun, 30 Nov 2008 16:57:28 +0000 |
parents | dea986389c57 |
children | e623323d409f |
rev | line source |
---|---|
6738 | 1 /* |
2 * Dirac decoder support via Schroedinger libraries | |
3 * Copyright (c) 2008 BBC, Anuradha Suraparaju <asuraparaju at gmail dot com > | |
4 * | |
5 * This file is part of FFmpeg. | |
6 * | |
7 * FFmpeg is free software; you can redistribute it and/or | |
8 * modify it under the terms of the GNU Lesser General Public | |
9 * License as published by the Free Software Foundation; either | |
10 * version 2.1 of the License, or (at your option) any later version. | |
11 * | |
12 * FFmpeg is distributed in the hope that it will be useful, | |
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * Lesser General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU Lesser General Public | |
18 * License along with FFmpeg; if not, write to the Free Software | |
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 */ | |
21 | |
22 /** | |
23 * @file libschroedingerdec.c | |
24 * Dirac decoder support via libschroedinger-1.0 libraries. More details about | |
25 * the Schroedinger project can be found at http://www.diracvideo.org/. | |
26 * The library implements Dirac Specification Version 2.2. | |
27 * (http://dirac.sourceforge.net/specification.html). | |
28 */ | |
29 | |
30 #include "avcodec.h" | |
31 #include "libdirac_libschro.h" | |
32 #include "libschroedinger.h" | |
33 | |
34 #undef NDEBUG | |
35 #include <assert.h> | |
36 | |
37 | |
38 #include <schroedinger/schro.h> | |
39 #include <schroedinger/schrodebug.h> | |
40 #include <schroedinger/schrovideoformat.h> | |
41 | |
42 /** libschroedinger decoder private data */ | |
43 typedef struct FfmpegSchroDecoderParams | |
44 { | |
45 /** Schroedinger video format */ | |
46 SchroVideoFormat *format; | |
47 | |
48 /** Schroedinger frame format */ | |
49 SchroFrameFormat frame_format; | |
50 | |
51 /** decoder handle */ | |
52 SchroDecoder* decoder; | |
53 | |
54 /** queue storing decoded frames */ | |
55 FfmpegDiracSchroQueue dec_frame_queue; | |
56 | |
57 /** end of sequence signalled */ | |
58 int eos_signalled; | |
59 | |
60 /** end of sequence pulled */ | |
61 int eos_pulled; | |
62 | |
63 /** decoded picture */ | |
64 AVPicture dec_pic; | |
65 } FfmpegSchroDecoderParams; | |
66 | |
7234
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
67 typedef struct FfmpegSchroParseUnitContext |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
68 { |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
69 const uint8_t *buf; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
70 int buf_size; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
71 } FfmpegSchroParseUnitContext; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
72 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
73 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
74 static void libschroedinger_decode_buffer_free (SchroBuffer *schro_buf, |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
75 void *priv); |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
76 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
77 static void FfmpegSchroParseContextInit (FfmpegSchroParseUnitContext *parse_ctx, |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
78 const uint8_t *buf, int buf_size) |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
79 { |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
80 parse_ctx->buf = buf; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
81 parse_ctx->buf_size = buf_size; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
82 } |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
83 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
84 static SchroBuffer* FfmpegFindNextSchroParseUnit (FfmpegSchroParseUnitContext *parse_ctx) |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
85 { |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
86 SchroBuffer *enc_buf = NULL; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
87 int next_pu_offset = 0; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
88 unsigned char *in_buf; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
89 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
90 if (parse_ctx->buf_size < 13 || |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
91 parse_ctx->buf[0] != 'B' || |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
92 parse_ctx->buf[1] != 'B' || |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
93 parse_ctx->buf[2] != 'C' || |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
94 parse_ctx->buf[3] != 'D') |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
95 return NULL; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
96 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
97 next_pu_offset = (parse_ctx->buf[5] << 24) + |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
98 (parse_ctx->buf[6] << 16) + |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
99 (parse_ctx->buf[7] << 8) + |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
100 parse_ctx->buf[8]; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
101 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
102 if (next_pu_offset == 0 && |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
103 SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(parse_ctx->buf[4])) |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
104 next_pu_offset = 13; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
105 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
106 if (next_pu_offset <= 0 || parse_ctx->buf_size < next_pu_offset) |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
107 return NULL; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
108 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
109 in_buf = av_malloc(next_pu_offset); |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
110 memcpy (in_buf, parse_ctx->buf, next_pu_offset); |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
111 enc_buf = schro_buffer_new_with_data (in_buf, next_pu_offset); |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
112 enc_buf->free = libschroedinger_decode_buffer_free; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
113 enc_buf->priv = in_buf; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
114 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
115 parse_ctx->buf += next_pu_offset; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
116 parse_ctx->buf_size -= next_pu_offset; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
117 |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
118 return enc_buf; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
119 } |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
120 |
6738 | 121 /** |
122 * Returns FFmpeg chroma format. | |
123 */ | |
124 static enum PixelFormat GetFfmpegChromaFormat(SchroChromaFormat schro_pix_fmt) | |
125 { | |
126 int num_formats = sizeof(ffmpeg_schro_pixel_format_map) / | |
127 sizeof(ffmpeg_schro_pixel_format_map[0]); | |
128 int idx; | |
129 | |
130 for (idx = 0; idx < num_formats; ++idx) { | |
131 if (ffmpeg_schro_pixel_format_map[idx].schro_pix_fmt == schro_pix_fmt) { | |
132 return ffmpeg_schro_pixel_format_map[idx].ff_pix_fmt; | |
133 } | |
134 } | |
135 return PIX_FMT_NONE; | |
136 } | |
137 | |
138 static int libschroedinger_decode_init(AVCodecContext *avccontext) | |
139 { | |
140 | |
141 FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data ; | |
142 /* First of all, initialize our supporting libraries. */ | |
143 schro_init(); | |
144 | |
145 schro_debug_set_level(avccontext->debug); | |
146 p_schro_params->decoder = schro_decoder_new(); | |
147 schro_decoder_set_skip_ratio(p_schro_params->decoder, 1); | |
148 | |
149 if (!p_schro_params->decoder) | |
150 return -1; | |
151 | |
152 /* Initialize the decoded frame queue. */ | |
153 ff_dirac_schro_queue_init (&p_schro_params->dec_frame_queue); | |
154 return 0 ; | |
155 } | |
156 | |
157 static void libschroedinger_decode_buffer_free (SchroBuffer *schro_buf, | |
158 void *priv) | |
159 { | |
160 av_freep(&priv); | |
161 } | |
162 | |
163 static void libschroedinger_decode_frame_free (void *frame) | |
164 { | |
165 schro_frame_unref(frame); | |
166 } | |
167 | |
168 static void libschroedinger_handle_first_access_unit(AVCodecContext *avccontext) | |
169 { | |
170 FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data; | |
171 SchroDecoder *decoder = p_schro_params->decoder; | |
172 | |
173 p_schro_params->format = schro_decoder_get_video_format (decoder); | |
174 | |
175 /* Tell FFmpeg about sequence details. */ | |
176 if(avcodec_check_dimensions(avccontext, p_schro_params->format->width, | |
177 p_schro_params->format->height) < 0) { | |
178 av_log(avccontext, AV_LOG_ERROR, "invalid dimensions (%dx%d)\n", | |
179 p_schro_params->format->width, p_schro_params->format->height); | |
180 avccontext->height = avccontext->width = 0; | |
6754 | 181 return; |
6738 | 182 } |
183 avccontext->height = p_schro_params->format->height; | |
184 avccontext->width = p_schro_params->format->width; | |
185 avccontext->pix_fmt = | |
186 GetFfmpegChromaFormat(p_schro_params->format->chroma_format); | |
187 | |
188 if (ff_get_schro_frame_format( p_schro_params->format->chroma_format, | |
189 &p_schro_params->frame_format) == -1) { | |
190 av_log (avccontext, AV_LOG_ERROR, | |
191 "This codec currently only supports planar YUV 4:2:0, 4:2:2 " | |
192 "and 4:4:4 formats.\n"); | |
6754 | 193 return; |
6738 | 194 } |
195 | |
196 avccontext->time_base.den = p_schro_params->format->frame_rate_numerator; | |
197 avccontext->time_base.num = p_schro_params->format->frame_rate_denominator; | |
198 | |
199 if (p_schro_params->dec_pic.data[0] == NULL) | |
200 { | |
201 avpicture_alloc(&p_schro_params->dec_pic, | |
202 avccontext->pix_fmt, | |
203 avccontext->width, | |
204 avccontext->height); | |
205 } | |
206 } | |
207 | |
208 static int libschroedinger_decode_frame(AVCodecContext *avccontext, | |
209 void *data, int *data_size, | |
210 const uint8_t *buf, int buf_size) | |
211 { | |
212 | |
213 FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data; | |
214 SchroDecoder *decoder = p_schro_params->decoder; | |
215 SchroVideoFormat *format; | |
216 AVPicture *picture = data; | |
217 SchroBuffer *enc_buf; | |
218 SchroFrame* frame; | |
219 int state; | |
220 int go = 1; | |
7234
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
221 int outer = 1; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
222 FfmpegSchroParseUnitContext parse_ctx; |
6738 | 223 |
224 *data_size = 0; | |
225 | |
7234
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
226 FfmpegSchroParseContextInit (&parse_ctx, buf, buf_size); |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
227 if (buf_size == 0) { |
6738 | 228 if (!p_schro_params->eos_signalled) { |
229 state = schro_decoder_push_end_of_stream(decoder); | |
230 p_schro_params->eos_signalled = 1; | |
231 } | |
232 } | |
233 | |
7234
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
234 /* Loop through all the individual parse units in the input buffer */ |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
235 do { |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
236 if ((enc_buf = FfmpegFindNextSchroParseUnit(&parse_ctx))) { |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
237 /* Push buffer into decoder. */ |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
238 state = schro_decoder_push (decoder, enc_buf); |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
239 if (state == SCHRO_DECODER_FIRST_ACCESS_UNIT) |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
240 libschroedinger_handle_first_access_unit(avccontext); |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
241 go = 1; |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
242 } |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
243 else |
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
244 outer = 0; |
6738 | 245 format = p_schro_params->format; |
246 | |
247 while (go) { | |
248 /* Parse data and process result. */ | |
249 state = schro_decoder_wait (decoder); | |
250 switch (state) | |
251 { | |
252 case SCHRO_DECODER_FIRST_ACCESS_UNIT: | |
253 libschroedinger_handle_first_access_unit (avccontext); | |
254 break; | |
255 | |
256 case SCHRO_DECODER_NEED_BITS: | |
257 /* Need more input data - stop iterating over what we have. */ | |
258 go = 0; | |
259 break; | |
260 | |
261 case SCHRO_DECODER_NEED_FRAME: | |
262 /* Decoder needs a frame - create one and push it in. */ | |
263 | |
264 frame = schro_frame_new_and_alloc(NULL, | |
265 p_schro_params->frame_format, | |
266 format->width, | |
267 format->height); | |
268 schro_decoder_add_output_picture (decoder, frame); | |
269 break; | |
270 | |
271 case SCHRO_DECODER_OK: | |
272 /* Pull a frame out of the decoder. */ | |
273 frame = schro_decoder_pull (decoder); | |
274 | |
275 if (frame) { | |
276 ff_dirac_schro_queue_push_back( | |
277 &p_schro_params->dec_frame_queue, | |
278 frame); | |
279 } | |
280 break; | |
281 case SCHRO_DECODER_EOS: | |
282 go = 0; | |
283 p_schro_params->eos_pulled = 1; | |
284 schro_decoder_reset (decoder); | |
7234
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
285 outer = 0; |
6738 | 286 break; |
287 | |
288 case SCHRO_DECODER_ERROR: | |
289 return -1; | |
290 break; | |
291 } | |
292 } | |
7234
dea986389c57
Parse frames to feed the decoder with individual parse units.
benoit
parents:
7040
diff
changeset
|
293 } while(outer); |
6738 | 294 |
295 /* Grab next frame to be returned from the top of the queue. */ | |
296 frame = ff_dirac_schro_queue_pop(&p_schro_params->dec_frame_queue); | |
297 | |
298 if (frame != NULL) { | |
299 memcpy (p_schro_params->dec_pic.data[0], | |
300 frame->components[0].data, | |
301 frame->components[0].length); | |
302 | |
303 memcpy (p_schro_params->dec_pic.data[1], | |
304 frame->components[1].data, | |
305 frame->components[1].length); | |
306 | |
307 memcpy (p_schro_params->dec_pic.data[2], | |
308 frame->components[2].data, | |
309 frame->components[2].length); | |
310 | |
311 /* Fill picture with current buffer data from Schroedinger. */ | |
312 avpicture_fill(picture, p_schro_params->dec_pic.data[0], | |
313 avccontext->pix_fmt, | |
314 avccontext->width, avccontext->height); | |
315 | |
316 *data_size = sizeof(AVPicture); | |
317 | |
318 /* Now free the frame resources. */ | |
319 libschroedinger_decode_frame_free (frame); | |
320 } | |
321 return buf_size; | |
322 } | |
323 | |
324 | |
325 static int libschroedinger_decode_close(AVCodecContext *avccontext) | |
326 { | |
327 FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data; | |
328 /* Free the decoder. */ | |
329 schro_decoder_free (p_schro_params->decoder); | |
330 av_freep(&p_schro_params->format); | |
331 | |
332 avpicture_free (&p_schro_params->dec_pic); | |
333 | |
334 /* Free data in the output frame queue. */ | |
335 ff_dirac_schro_queue_free (&p_schro_params->dec_frame_queue, | |
336 libschroedinger_decode_frame_free); | |
337 | |
338 return 0 ; | |
339 } | |
340 | |
341 static void libschroedinger_flush (AVCodecContext *avccontext) | |
342 { | |
343 /* Got a seek request. Free the decoded frames queue and then reset | |
344 * the decoder */ | |
345 FfmpegSchroDecoderParams *p_schro_params = avccontext->priv_data; | |
346 | |
347 /* Free data in the output frame queue. */ | |
348 ff_dirac_schro_queue_free (&p_schro_params->dec_frame_queue, | |
349 libschroedinger_decode_frame_free); | |
350 | |
351 ff_dirac_schro_queue_init (&p_schro_params->dec_frame_queue); | |
352 schro_decoder_reset(p_schro_params->decoder); | |
353 p_schro_params->eos_pulled = 0; | |
354 p_schro_params->eos_signalled = 0; | |
355 } | |
356 | |
357 AVCodec libschroedinger_decoder = { | |
358 "libschroedinger", | |
359 CODEC_TYPE_VIDEO, | |
360 CODEC_ID_DIRAC, | |
361 sizeof(FfmpegSchroDecoderParams), | |
362 libschroedinger_decode_init, | |
363 NULL, | |
364 libschroedinger_decode_close, | |
365 libschroedinger_decode_frame, | |
366 CODEC_CAP_DELAY, | |
6819
43bede126ef6
missing codec long names by Stefano Sabatini, stefano.sabatini-lala poste it
diego
parents:
6757
diff
changeset
|
367 .flush = libschroedinger_flush, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6819
diff
changeset
|
368 .long_name = NULL_IF_CONFIG_SMALL("libschroedinger Dirac 2.2"), |
6738 | 369 }; |