⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 swfdec_net_stream.c

📁 Swfdec is a decoder/renderer for Macromedia Flash animations. The decoding and rendering engine is
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Swfdec * Copyright (C) 2007 Benjamin Otte <otte@gnome.org> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. *  * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * Lesser General Public License for more details. *  * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor,  * Boston, MA  02110-1301  USA */#ifdef HAVE_CONFIG_H#include "config.h"#endif#include <math.h>#include "swfdec_net_stream.h"#include "swfdec_amf.h"#include "swfdec_as_strings.h"#include "swfdec_audio_flv.h"#include "swfdec_debug.h"#include "swfdec_loader_internal.h"#include "swfdec_loadertarget.h"/* NB: code and level must be rooted gc-strings */static voidswfdec_net_stream_onstatus (SwfdecNetStream *stream, const char *code, const char *level){  SwfdecAsValue val;  SwfdecAsObject *object;  object = swfdec_as_object_new (SWFDEC_AS_OBJECT (stream)->context);  if (!object)    return;  SWFDEC_INFO ("emitting onStatus for %s %s", level, code);  SWFDEC_AS_VALUE_SET_STRING (&val, code);  swfdec_as_object_set_variable (object, SWFDEC_AS_STR_code, &val);  SWFDEC_AS_VALUE_SET_STRING (&val, level);  swfdec_as_object_set_variable (object, SWFDEC_AS_STR_level, &val);  SWFDEC_AS_VALUE_SET_OBJECT (&val, object);  swfdec_as_object_call (SWFDEC_AS_OBJECT (stream), SWFDEC_AS_STR_onStatus, 1, &val, NULL);}static void swfdec_net_stream_update_playing (SwfdecNetStream *stream);static voidswfdec_net_stream_video_goto (SwfdecNetStream *stream, guint timestamp){  SwfdecBuffer *buffer;  SwfdecVideoFormat format;  cairo_surface_t *old;  gboolean process_events;  guint process_events_from;  SWFDEC_LOG ("goto %ums", timestamp);  process_events = timestamp == stream->next_time;  process_events_from = MIN (stream->next_time, stream->current_time + 1);  old = stream->surface;  if (stream->surface) {    cairo_surface_destroy (stream->surface);    stream->surface = NULL;  }  if (stream->flvdecoder->video) {    buffer = swfdec_flv_decoder_get_video (stream->flvdecoder, timestamp,	FALSE, &format, &stream->current_time, &stream->next_time);  } else {    buffer = NULL;  }  if (buffer == NULL) {    SWFDEC_ERROR ("got no buffer - no video available?");  } else {    if (format != stream->format) {      if (stream->decoder)	swfdec_video_decoder_free (stream->decoder);      stream->format = format;      stream->decoder = swfdec_video_decoder_new (format);    }    if (stream->decoder) {      stream->surface = swfdec_video_decoder_decode (stream->decoder, buffer);    }    if (stream->surface) {      GList *walk;      for (walk = stream->movies; walk; walk = walk->next) {	swfdec_video_movie_new_image (walk->data, stream->surface);      }    }  }  if (stream->next_time <= stream->current_time) {    if (swfdec_flv_decoder_is_eof (stream->flvdecoder)) {      swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Play_Stop, SWFDEC_AS_STR_status);    } else {      stream->buffering = TRUE;      swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Buffer_Empty,	  SWFDEC_AS_STR_status);    }    swfdec_net_stream_update_playing (stream);  }  if (process_events) {    while (process_events_from <= stream->current_time) {      SwfdecAsValue name, value;      SwfdecBits bits;      SwfdecBuffer *event = swfdec_flv_decoder_get_data (stream->flvdecoder, process_events_from, &process_events_from);      if (!event)	break;      SWFDEC_LOG ("processing event from timestamp %u", process_events_from);      process_events_from++; /* increase so we get the next event next time */      swfdec_bits_init (&bits, event);      if (swfdec_amf_parse (SWFDEC_AS_OBJECT (stream)->context, &bits, 2, 	    SWFDEC_AMF_STRING, &name, SWFDEC_AMF_MIXED_ARRAY, &value) != 2) {	SWFDEC_ERROR ("could not parse data tag");      } else {	swfdec_as_object_call (SWFDEC_AS_OBJECT (stream), 	    SWFDEC_AS_VALUE_GET_STRING (&name), 1, &value, NULL);      }    }  }}static voidswfdec_net_stream_timeout (SwfdecTimeout *timeout){  SwfdecNetStream *stream = SWFDEC_NET_STREAM ((guchar *) timeout - G_STRUCT_OFFSET (SwfdecNetStream, timeout));  SWFDEC_LOG ("timeout fired");  stream->timeout.callback = NULL;  swfdec_net_stream_video_goto (stream, stream->next_time);  if (stream->next_time > stream->current_time) {    SWFDEC_LOG ("readding timeout");    stream->timeout.timestamp += SWFDEC_MSECS_TO_TICKS (stream->next_time - stream->current_time);    stream->timeout.callback = swfdec_net_stream_timeout;    swfdec_player_add_timeout (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (stream)->context), &stream->timeout);  } else {    if (stream->audio) {      /* FIXME: just unref and let it take care of removing itself? */      SWFDEC_LOG ("stopping audio due to EOS");      swfdec_audio_remove (stream->audio);      g_object_unref (stream->audio);      stream->audio = NULL;    }  }}static voidswfdec_net_stream_update_playing (SwfdecNetStream *stream){  SwfdecPlayer *player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (stream)->context);  gboolean should_play;      should_play = stream->playing; /* checks user-set play/pause */  should_play &= !stream->buffering; /* checks enough data is available */  should_play &= stream->flvdecoder != NULL; /* checks there even is something to play */  should_play &= stream->next_time > stream->current_time; /* checks if EOF */  if (should_play && stream->timeout.callback == NULL) {    SWFDEC_DEBUG ("starting playback");    stream->timeout.callback = swfdec_net_stream_timeout;    stream->timeout.timestamp = player->time + SWFDEC_MSECS_TO_TICKS (stream->next_time - stream->current_time);    swfdec_player_add_timeout (player, &stream->timeout);    if (stream->flvdecoder->audio) {      g_assert (stream->audio == NULL);      SWFDEC_LOG ("starting audio");      stream->audio = swfdec_audio_flv_new (player, 	  stream->flvdecoder, stream->current_time);    } else {      SWFDEC_LOG ("no audio");    }  } else if (!should_play && stream->timeout.callback != NULL) {    if (stream->audio) {      SWFDEC_LOG ("stopping audio");      swfdec_audio_remove (stream->audio);      g_object_unref (stream->audio);      stream->audio = NULL;    }    swfdec_player_remove_timeout (player, &stream->timeout);    stream->timeout.callback = NULL;    SWFDEC_DEBUG ("stopping playback");  }}/*** SWFDEC_LOADER_TARGET interface ***/static SwfdecPlayer *swfdec_net_stream_loader_target_get_player (SwfdecLoaderTarget *target){  return SWFDEC_PLAYER (SWFDEC_AS_OBJECT (target)->context);}static voidswfdec_net_stream_loader_target_error (SwfdecLoaderTarget *target,     SwfdecLoader *loader){  SwfdecNetStream *stream = SWFDEC_NET_STREAM (target);  if (stream->flvdecoder == NULL)    swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Play_StreamNotFound,	SWFDEC_AS_STR_error);}static voidswfdec_net_stream_loader_target_recheck (SwfdecNetStream *stream){  if (stream->buffering) {    guint first, last;    if (swfdec_flv_decoder_get_video_info (stream->flvdecoder, &first, &last)) {      guint current = MAX (first, stream->current_time);      if (current + stream->buffer_time <= last) {	swfdec_net_stream_video_goto (stream, current);	stream->buffering = FALSE;	swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Buffer_Full,	    SWFDEC_AS_STR_status);      }    } else {      SWFDEC_ERROR ("no video stream, how do we update buffering?");    }  }  swfdec_net_stream_update_playing (stream);}static voidswfdec_net_stream_loader_target_parse (SwfdecLoaderTarget *target,     SwfdecLoader *loader){  SwfdecNetStream *stream = SWFDEC_NET_STREAM (target);  SwfdecDecoderClass *klass;  gboolean recheck = FALSE;    if (loader->state != SWFDEC_LOADER_STATE_EOF && swfdec_buffer_queue_get_depth (loader->queue) == 0) {    SWFDEC_INFO ("nothing to do");    return;  }  if (stream->flvdecoder == NULL) {    /* FIXME: add mp3 support */    stream->flvdecoder = g_object_new (SWFDEC_TYPE_FLV_DECODER, NULL);    SWFDEC_DECODER (stream->flvdecoder)->player = SWFDEC_PLAYER (SWFDEC_AS_OBJECT (stream)->context);    SWFDEC_DECODER (stream->flvdecoder)->queue = loader->queue;    swfdec_net_stream_onstatus (stream, SWFDEC_AS_STR_NetStream_Play_Start,	SWFDEC_AS_STR_status);    swfdec_loader_set_data_type (loader, SWFDEC_LOADER_DATA_FLV);  }  klass = SWFDEC_DECODER_GET_CLASS (stream->flvdecoder);  g_return_if_fail (klass->parse);  while (TRUE) {    SwfdecStatus status = klass->parse (SWFDEC_DECODER (stream->flvdecoder));    switch (status) {      case SWFDEC_STATUS_OK:	break;      case SWFDEC_STATUS_INIT:	/* HACK for native flv playback */	swfdec_player_initialize (SWFDEC_PLAYER (SWFDEC_AS_OBJECT (stream)->context), 7,	    SWFDEC_DECODER (stream->flvdecoder)->rate, 	    SWFDEC_DECODER (stream->flvdecoder)->width, 	    SWFDEC_DECODER (stream->flvdecoder)->height);      case SWFDEC_STATUS_IMAGE:	recheck = TRUE;	break;      case SWFDEC_STATUS_ERROR:      case SWFDEC_STATUS_NEEDBITS:      case SWFDEC_STATUS_EOF:	goto out;      default:	g_assert_not_reached ();	return;    }  }out:  if (recheck)    swfdec_net_stream_loader_target_recheck (stream);}static voidswfdec_net_stream_loader_target_eof (SwfdecLoaderTarget *target,     SwfdecLoader *loader){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -