📄 swfdec_codec_gst.c
字号:
g_signal_connect (decoder, "pad-added", G_CALLBACK (swfdec_audio_decoder_gst_link), convert); caps = gst_caps_from_string ("audio/x-raw-int, endianness=byte_order, signed=(boolean)true, width=16, depth=16, rate=44100, channels=2"); g_assert (caps); if (!gst_element_link_filtered (fakesrc, decoder, player->srccaps) || !gst_element_link_filtered (convert, fakesink, caps)) { SWFDEC_ERROR ("linking failed"); swfdec_audio_decoder_gst_free (&player->decoder); return NULL; } gst_caps_unref (caps); if (gst_element_set_state (player->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { SWFDEC_ERROR ("failed to change sate"); swfdec_audio_decoder_gst_free (&player->decoder); return NULL; } return &player->decoder;}/*** VIDEO ***/typedef struct _SwfdecGstVideo SwfdecGstVideo;struct _SwfdecGstVideo { SwfdecVideoDecoder decoder; GMutex * mutex; /* mutex that blocks everything below */ GCond * cond; /* cond used to signal when stuff below changes */ volatile int refcount; /* refcount (d'oh) */ GstElement * pipeline; /* pipeline that is playing or NULL when done */ SwfdecBuffer * in; /* next input buffer or NULL */ SwfdecBuffer * out; /* available output or NULL */ int width; /* width of last output buffer */ int height; /* height of last output buffer */ GstCaps * srccaps; /* caps to set on buffers */ gboolean out_next; /* wether the pipeline expects input or output */ gboolean error; /* we're in an error state */};static voidswfdec_gst_video_unref (gpointer data, GObject *unused){ SwfdecGstVideo *player = data; if (!g_atomic_int_dec_and_test (&player->refcount)) return; g_cond_free (player->cond); g_mutex_free (player->mutex); gst_caps_unref (player->srccaps); if (player->in) swfdec_buffer_unref (player->in); if (player->out) swfdec_buffer_unref (player->out); g_slice_free (SwfdecGstVideo, player);}static voidswfdec_video_decoder_gst_free (SwfdecVideoDecoder *dec){ SwfdecGstVideo *player = (SwfdecGstVideo *) dec; GstElement *pipeline; g_mutex_lock (player->mutex); pipeline = player->pipeline; player->pipeline = NULL; g_cond_signal (player->cond); g_mutex_unlock (player->mutex); gst_element_set_state (pipeline, GST_STATE_NULL); g_object_unref (pipeline); swfdec_gst_video_unref (player, NULL);}static SwfdecBuffer *swfdec_video_decoder_gst_decode (SwfdecVideoDecoder *dec, SwfdecBuffer *buffer, guint *width, guint *height, guint *rowstride){ SwfdecGstVideo *player = (SwfdecGstVideo *) dec; g_mutex_lock (player->mutex); while (player->in != NULL && !player->error) { swfdec_cond_wait (player->cond, player->mutex); } player->in = buffer; g_cond_signal (player->cond); while (player->out == NULL && !player->error) { swfdec_cond_wait (player->cond, player->mutex); } if (player->error) { g_mutex_unlock (player->mutex); return NULL; } buffer = player->out; player->out = NULL; *width = player->width; *height = player->height; *rowstride = player->width * 4; g_mutex_unlock (player->mutex); return buffer;}static voidswfdec_video_decoder_gst_fakesrc_handoff (GstElement *fakesrc, GstBuffer *buf, GstPad *pad, SwfdecGstVideo *player){ g_mutex_lock (player->mutex); if (player->out_next) { player->error = TRUE; g_cond_signal (player->cond); g_mutex_unlock (player->mutex); return; } while (player->pipeline != NULL && player->in == NULL) swfdec_cond_wait (player->cond, player->mutex); if (player->pipeline == NULL) { g_mutex_unlock (player->mutex); return; } buf->data = g_memdup (player->in->data, player->in->length); buf->malloc_data = buf->data; buf->size = player->in->length; gst_buffer_set_caps (buf, player->srccaps); player->in = NULL; player->out_next = TRUE; g_cond_signal (player->cond); g_mutex_unlock (player->mutex);}static voidswfdec_video_decoder_gst_fakesink_handoff (GstElement *fakesrc, GstBuffer *buf, GstPad *pad, SwfdecGstVideo *player){ GstCaps *caps; g_mutex_lock (player->mutex); if (!player->out_next) { player->error = TRUE; g_cond_signal (player->cond); g_mutex_unlock (player->mutex); return; } caps = gst_buffer_get_caps (buf); if (caps) { GstStructure *structure = gst_caps_get_structure (caps, 0); if (!gst_structure_get_int (structure, "width", &player->width) || !gst_structure_get_int (structure, "height", &player->height)) { player->width = 0; player->height = 0; } gst_caps_unref (caps); } while (player->pipeline != NULL && player->out != NULL) swfdec_cond_wait (player->cond, player->mutex); if (player->pipeline == NULL) { g_mutex_unlock (player->mutex); return; } player->out = swfdec_buffer_new_for_data ( g_memdup (buf->data, buf->size), buf->size); player->out_next = FALSE; g_cond_signal (player->cond); g_mutex_unlock (player->mutex);}static voidswfdec_video_decoder_gst_link (GstElement *src, GstPad *pad, GstElement *sink){ if (!gst_element_link (src, sink)) { SWFDEC_ERROR ("no delayed link"); }}SwfdecVideoDecoder *swfdec_video_decoder_gst_new (SwfdecVideoFormat type){ SwfdecGstVideo *player; GstElement *fakesrc, *fakesink, *decoder, *csp; GstCaps *caps; if (!gst_init_check (NULL, NULL, NULL)) return NULL; switch (type) { case SWFDEC_VIDEO_FORMAT_H263: caps = gst_caps_from_string ("video/x-flash-video"); break; case SWFDEC_VIDEO_FORMAT_VP6: caps = gst_caps_from_string ("video/x-vp6-flash"); break; default: return NULL; } g_assert (caps); player = g_slice_new0 (SwfdecGstVideo); player->decoder.decode = swfdec_video_decoder_gst_decode; player->decoder.free = swfdec_video_decoder_gst_free; player->pipeline = gst_pipeline_new ("pipeline"); player->refcount = 1; g_assert (player->pipeline); player->mutex = g_mutex_new (); player->cond = g_cond_new (); player->srccaps = caps; fakesrc = gst_element_factory_make ("fakesrc", NULL); if (fakesrc == NULL) { SWFDEC_ERROR ("failed to create fakesrc"); swfdec_video_decoder_gst_free (&player->decoder); return NULL; } g_object_set (fakesrc, "signal-handoffs", TRUE, "can-activate-pull", FALSE, NULL); g_signal_connect (fakesrc, "handoff", G_CALLBACK (swfdec_video_decoder_gst_fakesrc_handoff), player); g_atomic_int_inc (&player->refcount); g_object_weak_ref (G_OBJECT (fakesrc), swfdec_gst_video_unref, player); gst_bin_add (GST_BIN (player->pipeline), fakesrc); fakesink = gst_element_factory_make ("fakesink", NULL); if (fakesink == NULL) { SWFDEC_ERROR ("failed to create fakesink"); swfdec_video_decoder_gst_free (&player->decoder); return NULL; } g_object_set (fakesink, "signal-handoffs", TRUE, NULL); g_signal_connect (fakesink, "handoff", G_CALLBACK (swfdec_video_decoder_gst_fakesink_handoff), player); g_atomic_int_inc (&player->refcount); g_object_weak_ref (G_OBJECT (fakesink), swfdec_gst_video_unref, player); gst_bin_add (GST_BIN (player->pipeline), fakesink); decoder = gst_element_factory_make ("decodebin", NULL); if (decoder == NULL) { SWFDEC_ERROR ("failed to create decoder"); swfdec_video_decoder_gst_free (&player->decoder); return NULL; } gst_bin_add (GST_BIN (player->pipeline), decoder); csp = gst_element_factory_make ("ffmpegcolorspace", NULL); if (csp == NULL) { SWFDEC_ERROR ("failed to create colorspace"); swfdec_video_decoder_gst_free (&player->decoder); return NULL; } gst_bin_add (GST_BIN (player->pipeline), csp); g_signal_connect (decoder, "pad-added", G_CALLBACK (swfdec_video_decoder_gst_link), csp);#if G_BYTE_ORDER == G_BIG_ENDIAN caps = gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, " "red_mask=16711680, green_mask=65280, blue_mask=255");#else caps = gst_caps_from_string ("video/x-raw-rgb, bpp=32, endianness=4321, depth=24, " "red_mask=65280, green_mask=16711680, blue_mask=-16777216");#endif g_assert (caps); if (!gst_element_link_filtered (fakesrc, decoder, player->srccaps) || !gst_element_link_filtered (csp, fakesink, caps)) { SWFDEC_ERROR ("linking failed"); swfdec_video_decoder_gst_free (&player->decoder); return NULL; } gst_caps_unref (caps); if (gst_element_set_state (player->pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { SWFDEC_ERROR ("failed to change sate"); swfdec_video_decoder_gst_free (&player->decoder); return NULL; } return &player->decoder;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -