2 * Copyright (C) 2006 Benjamin Otte <otte@gnome.org>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301 USA
27 #include "swfdec_codec_audio.h"
28 #include "swfdec_codec_video.h"
29 #include "swfdec_debug.h"
30 #include "swfdec_internal.h"
34 static AVCodecContext
*
35 swfdec_codec_ffmpeg_init (enum CodecID id
)
39 static gboolean initialized
= FALSE
;
43 avcodec_register_all ();
47 codec
= avcodec_find_decoder (id
);
51 ctx
= avcodec_alloc_context ();
52 if (avcodec_open (ctx
, codec
) < 0)
57 SWFDEC_ERROR ("failed to initialize playback via ffmpeg");
66 SwfdecAudioDecoder decoder
;
68 SwfdecBufferQueue
* queue
;
69 } SwfdecAudioDecoderFFMpeg
;
72 swfdec_codec_ffmpeg_convert (AVCodecContext
*ctx
, SwfdecBuffer
*buffer
)
75 guint count
, i
, j
, rate
;
78 /* do the common case fast */
79 if (ctx
->channels
== 2 && ctx
->sample_rate
== 44100) {
80 ret
= swfdec_buffer_new_and_alloc (buffer
->length
);
81 memcpy (ret
->data
, buffer
->data
, buffer
->length
);
85 switch (ctx
->sample_rate
) {
96 SWFDEC_ERROR ("unsupported sample rate %u", ctx
->sample_rate
);
99 if (ctx
->channels
== 1)
101 ret
= swfdec_buffer_new_and_alloc (buffer
->length
* rate
);
102 out
= (gint16
*) ret
->data
;
103 in
= (gint16
*) buffer
->data
;
104 count
= buffer
->length
/ 2;
106 for (i
= 0; i
< count
; i
++) {
107 for (j
= 0; j
< rate
; j
++) {
116 swfdec_audio_decoder_ffmpeg_push (SwfdecAudioDecoder
*dec
, SwfdecBuffer
*buffer
)
118 SwfdecAudioDecoderFFMpeg
*ffmpeg
= (SwfdecAudioDecoderFFMpeg
*) dec
;
122 SwfdecBuffer
*outbuf
= NULL
;
126 outbuf
= swfdec_buffer_new_and_alloc (AVCODEC_MAX_AUDIO_FRAME_SIZE
);
127 for (amount
= 0; amount
< buffer
->length
; amount
+= len
) {
129 out_size
= AVCODEC_MAX_AUDIO_FRAME_SIZE
;
130 len
= avcodec_decode_audio2 (ffmpeg
->ctx
, (short *) outbuf
->data
, &out_size
, buffer
->data
+ amount
, buffer
->length
- amount
);
133 SWFDEC_ERROR ("Error %d while decoding", len
);
134 swfdec_buffer_unref (outbuf
);
138 SwfdecBuffer
*convert
;
139 outbuf
->length
= out_size
;
140 convert
= swfdec_codec_ffmpeg_convert (ffmpeg
->ctx
, outbuf
);
141 if (convert
== NULL
) {
142 swfdec_buffer_unref (outbuf
);
145 swfdec_buffer_queue_push (ffmpeg
->queue
, convert
);
146 outbuf
->length
= AVCODEC_MAX_AUDIO_FRAME_SIZE
;
149 swfdec_buffer_unref (outbuf
);
152 static SwfdecBuffer
*
153 swfdec_audio_decoder_ffmpeg_pull (SwfdecAudioDecoder
*dec
)
155 SwfdecAudioDecoderFFMpeg
*ffmpeg
= (SwfdecAudioDecoderFFMpeg
*) dec
;
157 return swfdec_buffer_queue_pull_buffer (ffmpeg
->queue
);
161 swfdec_audio_decoder_ffmpeg_free (SwfdecAudioDecoder
*dec
)
163 SwfdecAudioDecoderFFMpeg
*ffmpeg
= (SwfdecAudioDecoderFFMpeg
*) dec
;
165 avcodec_close (ffmpeg
->ctx
);
166 av_free (ffmpeg
->ctx
);
167 swfdec_buffer_queue_unref (ffmpeg
->queue
);
169 g_slice_free (SwfdecAudioDecoderFFMpeg
, ffmpeg
);
173 swfdec_audio_decoder_ffmpeg_new (SwfdecAudioCodec type
, gboolean width
, SwfdecAudioFormat format
)
175 SwfdecAudioDecoderFFMpeg
*ffmpeg
;
180 case SWFDEC_AUDIO_CODEC_ADPCM
:
181 id
= CODEC_ID_ADPCM_SWF
;
183 case SWFDEC_AUDIO_CODEC_MP3
:
189 ctx
= swfdec_codec_ffmpeg_init (id
);
192 ffmpeg
= g_slice_new (SwfdecAudioDecoderFFMpeg
);
194 ffmpeg
->queue
= swfdec_buffer_queue_new ();
195 ffmpeg
->decoder
.out_format
= SWFDEC_AUDIO_FORMAT_STEREO_44100
;
196 ffmpeg
->decoder
.pull
= swfdec_audio_decoder_ffmpeg_pull
;
197 ffmpeg
->decoder
.push
= swfdec_audio_decoder_ffmpeg_push
;
198 ffmpeg
->decoder
.free
= swfdec_audio_decoder_ffmpeg_free
;
199 ctx
->sample_rate
= SWFDEC_AUDIO_FORMAT_RATE (format
);
200 ctx
->channels
= SWFDEC_AUDIO_FORMAT_N_CHANNELS (format
);
202 return &ffmpeg
->decoder
;
208 SwfdecVideoDecoder decoder
;
209 AVCodecContext
* ctx
; /* out context (d'oh) */
210 AVFrame
* frame
; /* the frame we use for decoding */
211 enum PixelFormat format
; /* format we must output */
212 } SwfdecVideoDecoderFFMpeg
;
214 static enum PixelFormat
215 swfdec_video_decoder_ffmpeg_get_format (SwfdecVideoCodec codec
)
217 switch (swfdec_video_codec_get_format (codec
)) {
218 case SWFDEC_VIDEO_FORMAT_RGBA
:
219 return PIX_FMT_RGB32
;
220 case SWFDEC_VIDEO_FORMAT_I420
:
221 return PIX_FMT_YUV420P
;
223 g_assert_not_reached ();
224 return PIX_FMT_RGB32
;
229 swfdec_video_decoder_ffmpeg_decode (SwfdecVideoDecoder
*dec
, SwfdecBuffer
*buffer
,
230 SwfdecVideoImage
*image
)
232 SwfdecVideoDecoderFFMpeg
*codec
= (SwfdecVideoDecoderFFMpeg
*) dec
;
234 guchar
*tmp
, *aligned
;
236 /* fullfill alignment and padding requirements */
237 tmp
= g_try_malloc (buffer
->length
+ ALIGNMENT
+ FF_INPUT_BUFFER_PADDING_SIZE
);
239 SWFDEC_WARNING ("Could not allocate temporary memory");
242 aligned
= (guchar
*) (((uintptr_t) tmp
+ ALIGNMENT
) & ~ALIGNMENT
);
243 memcpy (aligned
, buffer
->data
, buffer
->length
);
244 memset (aligned
+ buffer
->length
, 0, FF_INPUT_BUFFER_PADDING_SIZE
);
245 if (avcodec_decode_video (codec
->ctx
, codec
->frame
, &got_image
,
246 aligned
, buffer
->length
) < 0) {
248 SWFDEC_WARNING ("error decoding frame");
252 if (got_image
== 0) {
253 SWFDEC_WARNING ("did not get an image from decoding");
256 if (codec
->ctx
->pix_fmt
!= codec
->format
) {
257 SWFDEC_WARNING ("decoded to wrong format, expected %u, but got %u",
258 codec
->format
, codec
->ctx
->pix_fmt
);
261 image
->width
= codec
->ctx
->width
;
262 image
->height
= codec
->ctx
->height
;
264 image
->plane
[0] = codec
->frame
->data
[0];
265 image
->plane
[1] = codec
->frame
->data
[1];
266 image
->plane
[2] = codec
->frame
->data
[2];
267 image
->rowstride
[0] = codec
->frame
->linesize
[0];
268 image
->rowstride
[1] = codec
->frame
->linesize
[1];
269 image
->rowstride
[2] = codec
->frame
->linesize
[2];
274 swfdec_video_decoder_ffmpeg_free (SwfdecVideoDecoder
*dec
)
276 SwfdecVideoDecoderFFMpeg
*codec
= (SwfdecVideoDecoderFFMpeg
*) dec
;
278 avcodec_close (codec
->ctx
);
279 av_free (codec
->ctx
);
280 av_free (codec
->frame
);
285 swfdec_video_decoder_ffmpeg_new (SwfdecVideoCodec type
)
287 SwfdecVideoDecoderFFMpeg
*codec
;
292 case SWFDEC_VIDEO_CODEC_H263
:
295 case SWFDEC_VIDEO_CODEC_SCREEN
:
296 id
= CODEC_ID_FLASHSV
;
298 case SWFDEC_VIDEO_CODEC_VP6
:
304 ctx
= swfdec_codec_ffmpeg_init (id
);
308 codec
= g_new0 (SwfdecVideoDecoderFFMpeg
, 1);
309 codec
->decoder
.decode
= swfdec_video_decoder_ffmpeg_decode
;
310 codec
->decoder
.free
= swfdec_video_decoder_ffmpeg_free
;
312 codec
->frame
= avcodec_alloc_frame ();
313 codec
->format
= swfdec_video_decoder_ffmpeg_get_format (type
);
315 return &codec
->decoder
;
319 swfdec_video_ffmpeg_i420_to_rgb (SwfdecVideoImage
*image
)
321 struct SwsContext
*sws
;
325 sws
= sws_getContext (image
->width
, image
->height
, PIX_FMT_YUV420P
,
326 image
->width
, image
->height
, PIX_FMT_RGB32
, 0, NULL
, NULL
, NULL
);
328 SWFDEC_ERROR ("Could not get conversion context");
331 data
= g_try_malloc (image
->width
* image
->height
* 4);
333 SWFDEC_ERROR ("Out of memory");
334 sws_freeContext (sws
);
337 src
.data
[0] = (unsigned char *) image
->plane
[0];
338 src
.data
[1] = (unsigned char *) image
->plane
[1];
339 src
.data
[2] = (unsigned char *) image
->plane
[2];
341 src
.linesize
[0] = image
->rowstride
[0];
342 src
.linesize
[1] = image
->rowstride
[1];
343 src
.linesize
[2] = image
->rowstride
[2];
345 avpicture_fill (&dst
, data
, PIX_FMT_RGB32
, image
->width
, image
->height
);
346 sws_scale (sws
, src
.data
, src
.linesize
, 0, image
->height
,
347 dst
.data
, dst
.linesize
);
348 sws_freeContext (sws
);