📄 swfdec_flv_decoder.c
字号:
tag.timestamp = timestamp; tag.buffer = swfdec_bits_get_buffer (bits, -1); if (tag.buffer == NULL) { SWFDEC_WARNING ("no buffer, ignoring"); return; } if (flv->data->len == 0) { g_array_append_val (flv->data, tag); } else if (g_array_index (flv->data, SwfdecFlvDataTag, flv->data->len - 1).timestamp < tag.timestamp) { g_array_append_val (flv->data, tag); } else { guint idx; SWFDEC_WARNING ("timestamps of data buffers not increasing (last was %u, now %u)", g_array_index (flv->data, SwfdecFlvDataTag, flv->data->len - 1).timestamp, tag.timestamp); idx = swfdec_flv_decoder_find_data (flv, tag.timestamp); g_array_insert_val (flv->data, idx, tag); }}static SwfdecStatusswfdec_flv_decoder_parse_tag (SwfdecFlvDecoder *flv){ SwfdecDecoder *dec = SWFDEC_DECODER (flv); SwfdecBuffer *buffer; SwfdecBits bits; guint size, type, timestamp; SwfdecStatus ret = SWFDEC_STATUS_OK; buffer = swfdec_buffer_queue_peek (dec->queue, 4); if (buffer == NULL) return SWFDEC_STATUS_NEEDBITS; swfdec_bits_init (&bits, buffer); swfdec_bits_get_u8 (&bits); size = swfdec_bits_get_bu24 (&bits); swfdec_buffer_unref (buffer); buffer = swfdec_buffer_queue_pull (dec->queue, 11 + size); if (buffer == NULL) return SWFDEC_STATUS_NEEDBITS; swfdec_bits_init (&bits, buffer); type = swfdec_bits_get_u8 (&bits); /* I think I'm paranoid and complicated. I think I'm paranoid, manipulated */ if (size != swfdec_bits_get_bu24 (&bits)) { g_assert_not_reached (); } timestamp = swfdec_bits_get_bu24 (&bits); swfdec_bits_get_bu32 (&bits); SWFDEC_LOG ("new tag"); SWFDEC_LOG (" type %u", type); SWFDEC_LOG (" size %u", size); SWFDEC_LOG (" timestamp %u", timestamp); switch (type) { case 8: swfdec_flv_decoder_parse_audio_tag (flv, &bits, timestamp); break; case 9: ret = swfdec_flv_decoder_parse_video_tag (flv, &bits, timestamp); break; case 18: swfdec_flv_decoder_parse_data_tag (flv, &bits, timestamp); break; default: SWFDEC_WARNING ("unknown tag (type %u)", type); break; } swfdec_buffer_unref (buffer); flv->state = SWFDEC_STATE_LAST_TAG; return ret;}static SwfdecStatusswfdec_flv_decoder_parse (SwfdecDecoder *dec){ SwfdecFlvDecoder *flv = SWFDEC_FLV_DECODER (dec); SwfdecStatus ret; switch (flv->state) { case SWFDEC_STATE_HEADER: ret = swfdec_flv_decoder_parse_header (flv); break; case SWFDEC_STATE_LAST_TAG: ret = swfdec_flv_decoder_parse_last_tag (flv); break; case SWFDEC_STATE_TAG: ret = swfdec_flv_decoder_parse_tag (flv); break; case SWFDEC_STATE_EOF: ret = SWFDEC_STATUS_EOF; break; default: g_assert_not_reached (); ret = SWFDEC_STATUS_ERROR; break; } return ret;}static voidswfdec_flv_decoder_class_init (SwfdecFlvDecoderClass *class){ GObjectClass *object_class = G_OBJECT_CLASS (class); SwfdecDecoderClass *decoder_class = SWFDEC_DECODER_CLASS (class); object_class->dispose = swfdec_flv_decoder_dispose; decoder_class->parse = swfdec_flv_decoder_parse;}static voidswfdec_flv_decoder_init (SwfdecFlvDecoder *flv){ flv->state = SWFDEC_STATE_HEADER;}SwfdecBuffer *swfdec_flv_decoder_get_video (SwfdecFlvDecoder *flv, guint timestamp, gboolean keyframe, SwfdecVideoFormat *format, guint *real_timestamp, guint *next_timestamp){ guint id, offset; SwfdecFlvVideoTag *tag; g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), NULL); g_return_val_if_fail (flv->video != NULL, NULL); if (flv->video->len == 0) { if (next_timestamp) *next_timestamp = 0; if (real_timestamp) *real_timestamp = 0; if (format) *format = SWFDEC_VIDEO_FORMAT_UNDEFINED; return NULL; } offset = g_array_index (flv->video, SwfdecFlvVideoTag, 0).timestamp; timestamp += offset; id = swfdec_flv_decoder_find_video (flv, timestamp); tag = &g_array_index (flv->video, SwfdecFlvVideoTag, id); if (keyframe) { while (id > 0 && tag->frame_type != 1) { id--; tag--; } } if (next_timestamp) { if (id + 1 >= flv->video->len) *next_timestamp = 0; else *next_timestamp = g_array_index (flv->video, SwfdecFlvVideoTag, id + 1).timestamp - offset; } if (real_timestamp) *real_timestamp = tag->timestamp - offset; if (format) *format = tag->format; return tag->buffer;}gbooleanswfdec_flv_decoder_get_video_info (SwfdecFlvDecoder *flv, guint *first_timestamp, guint *last_timestamp){ g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), FALSE); if (flv->video == NULL) return FALSE; if (flv->video->len == 0) { if (first_timestamp) *first_timestamp = 0; if (last_timestamp) *last_timestamp = 0; return TRUE; } if (first_timestamp) *first_timestamp = g_array_index (flv->video, SwfdecFlvVideoTag, 0).timestamp; if (last_timestamp) *last_timestamp = g_array_index (flv->video, SwfdecFlvVideoTag, flv->video->len - 1).timestamp; return TRUE;}SwfdecBuffer *swfdec_flv_decoder_get_audio (SwfdecFlvDecoder *flv, guint timestamp, SwfdecAudioFormat *codec_format, gboolean *width, SwfdecAudioOut *format, guint *real_timestamp, guint *next_timestamp){ guint id, offset; SwfdecFlvAudioTag *tag; g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), NULL); g_return_val_if_fail (flv->audio != NULL, NULL); if (flv->audio->len == 0) { if (next_timestamp) *next_timestamp = 0; if (real_timestamp) *real_timestamp = 0; if (codec_format) *codec_format = SWFDEC_AUDIO_FORMAT_UNDEFINED; if (width) *width = TRUE; if (format) *format = SWFDEC_AUDIO_OUT_STEREO_44100; return NULL; } offset = g_array_index (flv->audio, SwfdecFlvAudioTag, 0).timestamp; timestamp += offset; id = swfdec_flv_decoder_find_audio (flv, timestamp); if (next_timestamp) { if (id + 1 >= flv->audio->len) *next_timestamp = 0; else *next_timestamp = g_array_index (flv->audio, SwfdecFlvAudioTag, id + 1).timestamp - offset; } tag = &g_array_index (flv->audio, SwfdecFlvAudioTag, id); if (real_timestamp) *real_timestamp = tag->timestamp - offset; if (codec_format) *codec_format = tag->format; if (width) *width = tag->width; if (format) *format = tag->original_format; return tag->buffer;}/** * swfdec_flv_decoder_get_data: * @flv: a #SwfdecFlvDecoder * @timestamp: timestamp to look for * @real_timestamp: the timestamp of the returned buffer, if any * * Finds the next data event with a timestamp of at least @timestamp. If one * exists, it is returned, and its real timestamp put into @real_timestamp. * Otherwise, %NULL is returned. * * Returns: a #SwfdecBuffer containing the next data or NULL if none **/SwfdecBuffer *swfdec_flv_decoder_get_data (SwfdecFlvDecoder *flv, guint timestamp, guint *real_timestamp){ guint id; SwfdecFlvDataTag *tag; g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), NULL); if (flv->data == NULL || flv->data->len == 0) return NULL; id = swfdec_flv_decoder_find_data (flv, timestamp); tag = &g_array_index (flv->data, SwfdecFlvDataTag, id); while (tag->timestamp < timestamp) { id++; if (id >= flv->data->len) return NULL; tag++; } if (real_timestamp) *real_timestamp = tag->timestamp; return tag->buffer;}/*** HACK ***//* This is a hack to allow native FLV playback IN SwfdecPlayer */#include "swfdec_loadertarget.h"#include "swfdec_net_stream.h"#include "swfdec_sprite.h"#include "swfdec_video_movie.h"#if 0static voidnotify_initialized (SwfdecPlayer *player, GParamSpec *pspec, SwfdecVideoMovie *movie){ movie->video->width = player->width; movie->video->height = player->height; swfdec_movie_queue_update (SWFDEC_MOVIE (movie), SWFDEC_MOVIE_INVALID_MATRIX); swfdec_movie_invalidate (SWFDEC_MOVIE (movie));}#endifgbooleanswfdec_flv_decoder_is_eof (SwfdecFlvDecoder *flv){ g_return_val_if_fail (SWFDEC_IS_FLV_DECODER (flv), TRUE); return flv->state == SWFDEC_STATE_EOF;}voidswfdec_flv_decoder_eof (SwfdecFlvDecoder *flv){ g_return_if_fail (SWFDEC_IS_FLV_DECODER (flv)); flv->state = SWFDEC_STATE_EOF;}SwfdecMovie *swfdec_flv_decoder_add_movie (SwfdecFlvDecoder *flv, SwfdecMovie *parent){ //g_assert_not_reached (); return NULL;#if 0 SwfdecContent *content = swfdec_content_new (0); SwfdecMovie *movie; SwfdecVideo *video; SwfdecConnection *conn; SwfdecNetStream *stream; /* set up the video movie */ video = g_object_new (SWFDEC_TYPE_VIDEO, NULL); video->width = G_MAXUINT; video->height = G_MAXUINT; content->graphic = SWFDEC_GRAPHIC (video); content->free = TRUE; movie = swfdec_movie_new (parent, content); g_object_weak_ref (G_OBJECT (movie), (GWeakNotify) g_object_unref, video); g_signal_connect (SWFDEC_ROOT_MOVIE (parent)->player, "notify::initialized", G_CALLBACK (notify_initialized), movie); /* set up the playback stream */ conn = swfdec_connection_new (SWFDEC_ROOT_MOVIE (parent)->player->jscx); stream = swfdec_net_stream_new (SWFDEC_ROOT_MOVIE (parent)->player, conn); swfdec_net_stream_set_loader (stream, SWFDEC_ROOT_MOVIE (parent)->loader); stream->flvdecoder = flv; swfdec_video_movie_set_input (SWFDEC_VIDEO_MOVIE (movie), &stream->input); swfdec_net_stream_set_playing (stream, TRUE); g_object_unref (conn); g_object_unref (stream); return movie;#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -