static SwfdecScript * load_script (const char *filename) { SwfdecBuffer *file, *buffer; SwfdecScript *script; GError *error = NULL; if (filename == NULL) filename = "default.sts"; file = swfdec_buffer_new_from_file (filename, &error); if (file == NULL) { g_print ("ERROR: %s\n", error->message); g_error_free (error); return NULL; } if (file->length < sizeof (SWFDEC_TEST_FILE_ID) + 1 || memcmp (file->data, SWFDEC_TEST_FILE_ID, sizeof (SWFDEC_TEST_FILE_ID) != 0)) { g_print ("ERROR: %s is not a Swfdec test script\n", filename); swfdec_buffer_unref (file); return NULL; } buffer = swfdec_buffer_new_subbuffer (file, sizeof (SWFDEC_TEST_FILE_ID), file->length - sizeof (SWFDEC_TEST_FILE_ID)); swfdec_buffer_unref (file); script = swfdec_script_new (buffer, "main", SWFDEC_TEST_VERSION); return script; }
/* returns: number of samples available */ static void swfdec_audio_stream_require (SwfdecAudioStream *stream, guint n_samples) { SwfdecAudioStreamClass *klass = SWFDEC_AUDIO_STREAM_GET_CLASS (stream); SwfdecBuffer *buffer; /* subclasses are responsible for having set a proper decoder */ g_assert (SWFDEC_IS_AUDIO_DECODER (stream->decoder)); while (stream->queue_size < n_samples && !stream->done) { /* if the decoder still has data */ buffer = swfdec_audio_decoder_pull (stream->decoder); if (buffer) { g_queue_push_tail (stream->queue, buffer); stream->queue_size += buffer->length / 4; continue; } /* otherwise get a new buffer from the decoder */ buffer = klass->pull (stream); if (buffer == NULL) { stream->buffering = TRUE; break; } swfdec_audio_decoder_push (stream->decoder, buffer); swfdec_buffer_unref (buffer); } }
static gsize swfdec_audio_flv_iterate (SwfdecAudio *audio, gsize remove) { SwfdecAudioFlv *flv = SWFDEC_AUDIO_FLV (audio); SwfdecBuffer *buffer; guint next; flv->playback_skip += remove; buffer = g_queue_peek_head (flv->playback_queue); while (buffer && flv->playback_skip >= swfdec_sound_buffer_get_n_samples (buffer, swfdec_audio_format_new (44100, 2, TRUE)) + swfdec_audio_format_get_granularity (swfdec_audio_format_new (44100, 2, TRUE))) { buffer = g_queue_pop_head (flv->playback_queue); SWFDEC_LOG ("removing buffer with %u samples", swfdec_sound_buffer_get_n_samples (buffer, swfdec_audio_format_new (44100, 2, TRUE))); flv->playback_skip -= swfdec_sound_buffer_get_n_samples (buffer, swfdec_audio_format_new (44100, 2, TRUE)); swfdec_buffer_unref (buffer); buffer = g_queue_peek_head (flv->playback_queue); } flv->timestamp += SWFDEC_SAMPLES_TO_TICKS (remove); if (!g_queue_is_empty (flv->playback_queue)) return G_MAXUINT; swfdec_flv_decoder_get_audio (flv->flvdecoder, SWFDEC_TICKS_TO_MSECS (flv->timestamp), NULL, NULL, NULL, &next); return next ? G_MAXUINT : 0; }
static void swfdec_sprite_dispose (GObject *object) { SwfdecSprite * sprite = SWFDEC_SPRITE (object); guint i; if (sprite->frames) { for (i = 0; i < sprite->n_frames; i++) { g_slist_foreach (sprite->frames[i].labels, (GFunc) g_free, NULL); g_slist_free (sprite->frames[i].labels); } g_free(sprite->frames); } for (i = 0; i < sprite->actions->len; i++) { SwfdecSpriteAction *cur = &g_array_index (sprite->actions, SwfdecSpriteAction, i); if (cur->buffer) swfdec_buffer_unref (cur->buffer); } g_array_free (sprite->actions, TRUE); sprite->actions = NULL; if (sprite->init_action) { swfdec_script_unref (sprite->init_action); sprite->init_action = NULL; } G_OBJECT_CLASS (swfdec_sprite_parent_class)->dispose (object); }
SwfdecBuffer * vivi_code_emitter_finish (ViviCodeEmitter *emitter, GError **error) { SwfdecBuffer *buffer; GSList *walk; g_return_val_if_fail (VIVI_IS_CODE_EMITTER (emitter), NULL); buffer = swfdec_bots_close (emitter->bots); emitter->bots = NULL; for (walk = emitter->later; walk; walk = walk->next) { Later *later = walk->data; if (!later->func (emitter, buffer, later->offset, later->data, error)) { swfdec_buffer_unref (buffer); buffer = NULL; break; } } g_slist_foreach (emitter->later, (GFunc) g_free, NULL); g_slist_free (emitter->later); emitter->later = NULL; g_hash_table_remove_all (emitter->labels); emitter->bots = swfdec_bots_open (); return buffer; }
/** * swfdec_buffer_queue_flush: * @queue: a #SwfdecBufferQueue * @n_bytes: amount of bytes to flush from the queue * * Removes the first @n_bytes bytes from the queue. */ void swfdec_buffer_queue_flush (SwfdecBufferQueue *queue, gsize n_bytes) { g_return_if_fail (queue != NULL); g_return_if_fail (n_bytes <= queue->depth); queue->depth -= n_bytes; queue->offset += n_bytes; SWFDEC_LOG ("flushing %zu bytes (%zu left)", n_bytes, queue->depth); while (n_bytes > 0) { SwfdecBuffer *buffer = queue->first_buffer->data; if (buffer->length <= n_bytes) { n_bytes -= buffer->length; queue->first_buffer = g_slist_remove (queue->first_buffer, buffer); } else { queue->first_buffer->data = swfdec_buffer_new_subbuffer (buffer, n_bytes, buffer->length - n_bytes); n_bytes = 0; } swfdec_buffer_unref (buffer); } if (queue->first_buffer == NULL) queue->last_buffer = NULL; }
static void swfdec_test_swfdec_socket_send (SwfdecSocket *sock, SwfdecBuffer *buffer) { SwfdecTestSwfdecSocket *test = SWFDEC_TEST_SWFDEC_SOCKET (sock); test->plugin.send (&test->plugin, buffer->data, buffer->length); swfdec_buffer_unref (buffer); }
char * swfdec_buffer_queue_pull_text (SwfdecBufferQueue *queue, guint version) { SwfdecBuffer *buffer; char *text; guint size, i, j; size = swfdec_buffer_queue_get_depth (queue); if (size == 0) { SWFDEC_LOG ("empty loader, returning empty string"); return g_strdup (""); } buffer = swfdec_buffer_queue_pull (queue, size); g_assert (buffer); if (version > 5) { for (i = 0; boms[i].length > 0; i++) { // FIXME: test what happens if we have BOM and nothing else if (size < boms[i].length) continue; for (j = 0; j < boms[i].length; j++) { if (buffer->data[j] != boms[i].data[j]) break; } if (j == boms[i].length) break; } if (!strcmp (boms[i].name, "UTF-8")) { if (!g_utf8_validate ((char *)buffer->data + boms[i].length, size - boms[i].length, NULL)) { SWFDEC_ERROR ("downloaded data is not valid UTF-8"); text = NULL; } else { text = g_strndup ((char *)buffer->data + boms[i].length, size - boms[i].length); } } else { text = g_convert ((char *)buffer->data + boms[i].length, size - boms[i].length, "UTF-8", boms[i].name, NULL, NULL, NULL); if (text == NULL) SWFDEC_ERROR ("downloaded data is not valid %s", boms[i].name); } } else { text = g_convert ((char *)buffer->data, size, "UTF-8", "LATIN1", NULL, NULL, NULL); if (text == NULL) SWFDEC_ERROR ("downloaded data is not valid LATIN1"); } swfdec_buffer_unref (buffer); return text; }
static void gst_swfdecbuffer_finalize (GstSwfdecBuffer * swfdecbuffer) { g_return_if_fail (swfdecbuffer != NULL); GST_LOG ("finalize %p", swfdecbuffer); swfdec_buffer_unref (swfdecbuffer->swfdec_buffer); ((GstMiniObjectClass *) buffer_parent_class)->finalize ((GstMiniObject *) swfdecbuffer); }
GstBuffer * swfdec_gst_buffer_new (SwfdecBuffer *buffer) { /* FIXME: make this a zero-copy operation */ GstBuffer *ret; g_return_val_if_fail (buffer != NULL , NULL); ret = gst_buffer_new_and_alloc (buffer->length); memcpy (GST_BUFFER_DATA (ret), buffer->data, buffer->length); swfdec_buffer_unref (buffer); return ret; }
static void swfdec_xml_socket_do_write (SwfdecXmlSocket *xml) { SwfdecBuffer *buffer; gsize written, length; do { buffer = swfdec_buffer_queue_peek_buffer (xml->send_queue); if (buffer == NULL) break; length = buffer->length; written = swfdec_socket_send (xml->socket, buffer); swfdec_buffer_unref (buffer); swfdec_buffer_queue_flush (xml->send_queue, written); } while (written == length); }
static void vivi_code_emitter_dispose (GObject *object) { ViviCodeEmitter *emit = VIVI_CODE_EMITTER (object); if (emit->bots) { SwfdecBuffer *buffer = swfdec_bots_close (emit->bots); swfdec_buffer_unref (buffer); emit->bots = NULL; } g_slist_foreach (emit->later, (GFunc) g_free, NULL); g_slist_free (emit->later); emit->later = NULL; g_hash_table_destroy (emit->labels); emit->labels = NULL; G_OBJECT_CLASS (vivi_code_emitter_parent_class)->dispose (object); }
/** * swfdec_buffer_queue_push: * @queue: a #SwfdecBufferQueue * @buffer: #SwfdecBuffer to append to @queue * * Appends the given @buffer to the buffers already in @queue. This function * will take ownership of the given @buffer. Use swfdec_buffer_ref () before * calling this function to keep a reference. **/ void swfdec_buffer_queue_push (SwfdecBufferQueue * queue, SwfdecBuffer * buffer) { g_return_if_fail (queue != NULL); g_return_if_fail (buffer != NULL); if (buffer->length == 0) { swfdec_buffer_unref (buffer); return; } queue->last_buffer = g_slist_append (queue->last_buffer, buffer); if (queue->first_buffer == NULL) { queue->first_buffer = queue->last_buffer; } else { queue->last_buffer = queue->last_buffer->next; } queue->depth += buffer->length; }
static void swfdec_load_object_dispose (GObject *object) { SwfdecLoadObject *load = SWFDEC_LOAD_OBJECT (object); if (load->loader) { swfdec_stream_set_target (SWFDEC_STREAM (load->loader), NULL); g_object_unref (load->loader); load->loader = NULL; } if (load->buffer) { swfdec_buffer_unref (load->buffer); load->buffer = NULL; } g_strfreev (load->header_names); g_strfreev (load->header_values); G_OBJECT_CLASS (swfdec_load_object_parent_class)->dispose (object); }
static gboolean swfdec_audio_stream_check_buffering (SwfdecAudioStream *stream) { SwfdecAudioStreamClass *klass; SwfdecBuffer *buffer; if (!stream->buffering || stream->done) return FALSE; klass = SWFDEC_AUDIO_STREAM_GET_CLASS (stream); buffer = klass->pull (stream); if (buffer == NULL) return FALSE; swfdec_audio_decoder_push (stream->decoder, buffer); swfdec_buffer_unref (buffer); stream->buffering = FALSE; g_signal_emit_by_name (stream, "new-data"); return stream->queue_size == 0; }
static gboolean swfdec_xml_socket_stream_target_parse (SwfdecStreamTarget *target, SwfdecStream *stream) { SwfdecXmlSocket *xml = SWFDEC_XML_SOCKET (target); SwfdecBufferQueue *queue; SwfdecBuffer *buffer; gsize len; /* parse until next 0 byte or take everything */ queue = swfdec_stream_get_queue (stream); while ((buffer = swfdec_buffer_queue_peek_buffer (queue))) { guchar *nul = memchr (buffer->data, 0, buffer->length); len = nul ? (gsize) (nul - buffer->data + 1) : buffer->length; g_assert (len > 0); swfdec_buffer_unref (buffer); buffer = swfdec_buffer_queue_pull (queue, len); swfdec_buffer_queue_push (xml->queue, buffer); if (nul) { len = swfdec_buffer_queue_get_depth (xml->queue); g_assert (len > 0); buffer = swfdec_buffer_queue_pull (xml->queue, len); if (!g_utf8_validate ((char *) buffer->data, len, NULL)) { SWFDEC_FIXME ("invalid utf8 sent through socket, what now?"); } else { SwfdecAsValue val; SWFDEC_AS_VALUE_SET_STRING (&val, swfdec_as_context_get_string ( swfdec_gc_object_get_context (xml), (char *) buffer->data)); swfdec_sandbox_use (xml->sandbox); swfdec_as_object_call (xml->target, SWFDEC_AS_STR_onData, 1, &val, NULL); swfdec_sandbox_unuse (xml->sandbox); } } } return FALSE; }
static SwfdecBuffer * swfdec_audio_flv_decode_one (SwfdecAudioFlv *flv) { SwfdecBuffer *buffer; guint format; SwfdecAudioFormat in; guint now, soon; if (g_queue_is_empty (flv->playback_queue)) { /* sync */ guint last; swfdec_flv_decoder_get_audio (flv->flvdecoder, SWFDEC_TICKS_TO_MSECS (flv->timestamp), NULL, NULL, &last, NULL); flv->playback_skip = SWFDEC_TICKS_TO_SAMPLES ( flv->timestamp - SWFDEC_MSECS_TO_TICKS (last)); flv->next_timestamp = last; SWFDEC_DEBUG ("syncing to %ums: next timestamp to decode is %ums, skipping %u samples", (guint) SWFDEC_TICKS_TO_MSECS (flv->timestamp), flv->next_timestamp, flv->playback_skip); } if (flv->decoder) buffer = swfdec_audio_decoder_pull (flv->decoder); else buffer = NULL; while (buffer == NULL) { if (flv->decoder && flv->next_timestamp == 0) return NULL; buffer = swfdec_flv_decoder_get_audio (flv->flvdecoder, flv->next_timestamp, &format, &in, &now, &soon); if (flv->next_timestamp != now) { /* FIXME: do sync on first frame here */ SWFDEC_WARNING ("FIXME: didn't get requested timestamp - still loading?"); } /* FIXME FIXME FIXME: This avoids decoding the last frame forever, however it ensures sync */ if (soon == 0) return NULL; flv->next_timestamp = soon; if (flv->in == 0) { /* init */ if (flv->decoder) { g_object_unref (flv->decoder); flv->decoder = NULL; } flv->format = format; flv->in = in; flv->decoder = swfdec_audio_decoder_new (flv->format, flv->in); if (flv->decoder == NULL) return NULL; /* This is a hack that ensures AAC codec data is always present, even if * the decoder gets initialized in the middle of the stream */ if (format == SWFDEC_AUDIO_CODEC_AAC) { SwfdecBuffer *tmp = swfdec_flv_decoder_get_audio (flv->flvdecoder, 0, &format, NULL, NULL, NULL); if (format == SWFDEC_AUDIO_CODEC_AAC && tmp->data[0] == 0 && tmp->length > 1) { tmp = swfdec_buffer_new_subbuffer (tmp, 1, tmp->length - 1); swfdec_audio_decoder_set_codec_data (flv->decoder, tmp); swfdec_buffer_unref (tmp); } } } else if (format != flv->format || in != flv->in) { SWFDEC_ERROR ("FIXME: format change not implemented"); return NULL; } else if (flv->decoder == NULL) { return NULL; } if (format == SWFDEC_AUDIO_CODEC_AAC) { SwfdecBuffer *data; SwfdecBits bits; guint type; swfdec_bits_init (&bits, buffer); type = swfdec_bits_get_u8 (&bits); switch (type) { case 0: data = swfdec_bits_get_buffer (&bits, -1); if (data) { swfdec_audio_decoder_set_codec_data (flv->decoder, data); swfdec_buffer_unref (data); } break; case 1: data = swfdec_bits_get_buffer (&bits, -1); if (data) { swfdec_audio_decoder_push (flv->decoder, data); swfdec_buffer_unref (data); } else { SWFDEC_ERROR ("no data in AAC data buffer?"); } break; default: SWFDEC_FIXME ("handle AAC type %u", type); break; } } else { swfdec_audio_decoder_push (flv->decoder, buffer); } if (flv->next_timestamp == 0) swfdec_audio_decoder_push (flv->decoder, NULL); buffer = swfdec_audio_decoder_pull (flv->decoder); } g_queue_push_tail (flv->playback_queue, buffer); return buffer; }