add blend mode tests
[swfdec.git] / swfdec / swfdec_audio_swf_stream.c
blob9a387535c8fc8a80e1d1ba3c9c2c86e76af62cce
1 /* Swfdec
2 * Copyright (C) 2008 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.
8 *
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
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
24 #include <string.h>
25 #include "swfdec_audio_swf_stream.h"
26 #include "swfdec_debug.h"
27 #include "swfdec_sprite.h"
28 #include "swfdec_tag.h"
31 G_DEFINE_TYPE (SwfdecAudioSwfStream, swfdec_audio_swf_stream, SWFDEC_TYPE_AUDIO_STREAM)
33 static void
34 swfdec_audio_swf_stream_dispose (GObject *object)
36 SwfdecAudioSwfStream *stream = SWFDEC_AUDIO_SWF_STREAM (object);
38 if (stream->sprite != NULL) {
39 g_object_unref (stream->sprite);
40 stream->sprite = NULL;
43 G_OBJECT_CLASS (swfdec_audio_swf_stream_parent_class)->dispose (object);
46 static void
47 swfdec_audio_swf_stream_head (SwfdecAudioSwfStream *stream, SwfdecBuffer *buffer)
49 SwfdecBits bits;
50 SwfdecAudioFormat playback_format, format;
51 guint playback_codec, codec;
52 int n_samples;
53 guint latency = 0;
55 swfdec_bits_init (&bits, buffer);
57 /* we don't care about playback suggestions */
58 playback_codec = swfdec_bits_getbits (&bits, 4);
59 playback_format = swfdec_audio_format_parse (&bits);
60 SWFDEC_LOG (" suggested playback format: %s", swfdec_audio_format_to_string (playback_format));
62 codec = swfdec_bits_getbits (&bits, 4);
63 format = swfdec_audio_format_parse (&bits);
64 n_samples = swfdec_bits_get_u16 (&bits);
65 SWFDEC_LOG (" codec: %u", codec);
66 SWFDEC_LOG (" format: %s", swfdec_audio_format_to_string (format));
67 SWFDEC_LOG (" samples: %u", n_samples);
69 switch (codec) {
70 case SWFDEC_AUDIO_CODEC_UNDEFINED:
71 if (swfdec_audio_format_is_16bit (format)) {
72 SWFDEC_WARNING ("undefined endianness for s16 sound");
73 /* just assume LE and hope it works (FIXME: want a switch for this?) */
74 codec = SWFDEC_AUDIO_CODEC_UNCOMPRESSED;
76 break;
77 case SWFDEC_AUDIO_CODEC_MP3:
78 /* latency seek */
79 latency = swfdec_bits_get_u16 (&bits);
80 break;
81 case SWFDEC_AUDIO_CODEC_ADPCM:
82 case SWFDEC_AUDIO_CODEC_UNCOMPRESSED:
83 case SWFDEC_AUDIO_CODEC_NELLYMOSER_8KHZ:
84 case SWFDEC_AUDIO_CODEC_NELLYMOSER:
85 break;
86 default:
87 SWFDEC_WARNING ("unknown codec %u", codec);
88 break;
91 swfdec_audio_stream_use_decoder (SWFDEC_AUDIO_STREAM (stream), codec, format);
94 static SwfdecBuffer *
95 swfdec_audio_swf_stream_block (SwfdecAudioSwfStream *stream, SwfdecBuffer *buffer)
97 SwfdecBits bits;
98 guint n_samples;
99 int skip;
101 swfdec_bits_init (&bits, buffer);
103 /* FIXME: we want accessor functions for this */
104 if (SWFDEC_AUDIO_STREAM (stream)->decoder->codec == SWFDEC_AUDIO_CODEC_MP3) {
105 n_samples = swfdec_bits_get_u16 (&bits);
106 skip = swfdec_bits_get_s16 (&bits);
108 buffer = swfdec_bits_get_buffer (&bits, -1);
109 /* use this to write out the stream data to stdout - nice way to get an mp3 file :) */
110 //write (1, (void *) buffer->data, buffer->length);
112 return buffer;
115 static SwfdecBuffer *
116 swfdec_audio_swf_stream_pull (SwfdecAudioStream *audio)
118 SwfdecAudioSwfStream *stream = SWFDEC_AUDIO_SWF_STREAM (audio);
119 SwfdecBuffer *buffer;
120 guint tag;
122 do {
123 if (!swfdec_sprite_get_action (stream->sprite, stream->id, &tag, &buffer)) {
124 if (swfdec_sprite_is_loaded (stream->sprite))
125 swfdec_audio_stream_done (audio);
126 buffer = NULL;
127 break;
129 stream->id++;
130 switch (tag) {
131 case SWFDEC_TAG_SOUNDSTREAMHEAD:
132 case SWFDEC_TAG_SOUNDSTREAMHEAD2:
133 swfdec_audio_swf_stream_head (stream, buffer);
134 break;
135 case SWFDEC_TAG_SOUNDSTREAMBLOCK:
136 buffer = swfdec_audio_swf_stream_block (stream, buffer);
137 break;
138 default:
139 break;
141 } while (tag != SWFDEC_TAG_SOUNDSTREAMBLOCK);
143 return buffer;
146 static void
147 swfdec_audio_swf_stream_class_init (SwfdecAudioSwfStreamClass *klass)
149 GObjectClass *object_class = G_OBJECT_CLASS (klass);
150 SwfdecAudioStreamClass *stream_class = SWFDEC_AUDIO_STREAM_CLASS (klass);
152 object_class->dispose = swfdec_audio_swf_stream_dispose;
154 stream_class->pull = swfdec_audio_swf_stream_pull;
157 static void
158 swfdec_audio_swf_stream_init (SwfdecAudioSwfStream *stream)
162 SwfdecAudio *
163 swfdec_audio_swf_stream_new (SwfdecPlayer *player, SwfdecSprite *sprite,
164 guint id)
166 SwfdecAudioSwfStream *stream;
167 guint i, tag;
168 SwfdecBuffer *buffer;
170 g_return_val_if_fail (SWFDEC_IS_PLAYER (player), NULL);
171 g_return_val_if_fail (SWFDEC_IS_SPRITE (sprite), NULL);
173 stream = g_object_new (SWFDEC_TYPE_AUDIO_SWF_STREAM, NULL);
174 stream->sprite = g_object_ref (sprite);
175 stream->id = id;
177 i = id;
178 do {
179 i--;
180 if (!swfdec_sprite_get_action (sprite, i, &tag, &buffer)) {
181 g_assert_not_reached ();
183 if (tag == SWFDEC_TAG_SOUNDSTREAMHEAD ||
184 tag == SWFDEC_TAG_SOUNDSTREAMHEAD2) {
185 swfdec_audio_swf_stream_head (stream, buffer);
186 goto found;
188 } while (i > 0);
189 SWFDEC_ERROR ("No SoundStreamHead tag found in sprite %u",
190 SWFDEC_CHARACTER (sprite)->id);
191 swfdec_audio_stream_done (SWFDEC_AUDIO_STREAM (stream));
193 found:
194 swfdec_audio_add (SWFDEC_AUDIO (stream), player);
195 return SWFDEC_AUDIO (stream);