gstreamer 是流水線型式運行 這無需多言
其框架異常之大 令愚眛的本人摸不著頭緒
尤為其具gtk之精神 : 用字串表式設定對向 這搞人的設計非常好的延序下來
在本文中 是計錄如何用gstreamer 將內存中的jpeg數據 解壓為RGB-既沒有說明頭的bmp
以下假設jpeg資料在 pJepg, jpeg資料常 jpegSize
第零步:
以下代碼用到了 appsink 所以請在頭檔案裡加上
#include "gst/gst.h"
#include <gio/gio.h>
#include <gst/app/gstappsink.h>
並在Makefile中加上參考到的庫:
LIB += -lgstreamer-0.10 -lgtk-x11-2.0
LIB += -lgstpbutils-0.10 -lgstinterfaces-0.10 -lgio-2.0
LIB += -lgstapp-0.10
第一步 : 建立流水線上的各棧 並串接起來
//初始化gstreamer:
gst_init(argc, argv); (不知道argc, argv者 輸入0,NULL就可以了);
GstElement *pPipeline;
GstElement *pSrcElement, *pJpegDecoder,*pColorspace, *pAppSink;
pPipeline = gst_pipeline_new("gstreamer jpegdecode");
pSrcElement =gst_element_factory_make ("giostreamsrc", "src");
pJpegDecoder = gst_element_factory_make("jpegdec", "jpegdecoder");
pColorspace =gst_element_factory_make("ffmpegcolorspace", "ffmdec");
pAppSink = gst_element_factory_make ("appsink","sink");
其中 pSrcElement 因為資料是由內存讀入 所以設為 giostreamsrc; 而輸出是自定義行為,所以用appSink
(gstreamer貌似沒有直接輸出到內存的管線 所以要自定意)
把這些棧連結起來:
pPipeline = gst_pipeline_new("gstreamer jpegdecode");
gst_bin_add_many (GST_BIN (pPipeline),pSrcElement, pJpegDecoder, pColorspace, pAppSink, NULL,NULL);
gst_element_link_many (pSrcElement,pJpegDecoder, pColorspace, pAppSink, NULL, NULL);
第二步: 設定初始的源內存於何處 (與第三步可易)
這裡用到GMemoryInputStream:
GMemoryInputStream*pStreamIn;
pStreamIn =G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (pJpeg,jpegSize, (GDestroyNotify) NULL));
g_object_set(G_OBJECT (pSrcElement), "stream", pStreamIn,NULL);
gst_object_unref(pStreamIn);
第三步 : 設定appsink要做的事 , 這裡需要設個函數指針 去把資料倒出來
函數指針原形為為 void (*p)(GstElement *pAppSink, void *pData);
我這定為 void WriteBuffer(GstElement *pAppSink, void*data) ;
設定個抓取對向:
GstCaps *pAppSinkCaps;
pAppSinkCaps= gst_caps_new_simple (
"video/x-raw-rgb",
"red_mask", G_TYPE_INT, 0x000000ff,
"green_mask", G_TYPE_INT, 0x0000ff00,
"blue_mask", G_TYPE_INT, 0x00ff0000,
"bpp",G_TYPE_INT,24,
"depth",G_TYPE_INT,24,
// "width",G_TYPE_INT, 640,
// "height", G_TYPE_INT,480,
NULL);
g_object_set(pSink, "emit-signals", TRUE, "caps", pAppSinkCaps,NULL);
g_signal_connect (pAppSink, "new-buffer", G_CALLBACK (WriteBuffer),NULL);
gst_caps_unref (pAppSinkCaps);
第四步 : 設定一個迴圈 其會在適當時機(就運行到appSink時)調用剛的WriteBuffer函數 :
GMainLoop *pLoop;
pLoop = g_main_loop_new(NULL, FALSE);
第五步:啟動流水線與迴圈:
gst_element_set_state (pPipeline,GST_STATE_PLAYING);
pLoop = g_main_loop_new(NULL, FALSE);
g_main_loop_run (pLoop);
gst_element_set_state (pPipeline,GST_STATE_READY );
第六步 實作 void WriteBuffer(GstElement *pAppSink, void *data):
這裡是用函數
BMPwriter儲存為BMP , 這種講原始RGB存為BMP的函數, 網上源代碼太多了 這裡就略去
void WriteBuffer(GstElement *pAppSink, void *data)
{
GstBuffer *pBuffer;
GstStructure
*pStructure;
int width,height;
intbpp;
pBuffer =gst_app_sink_pull_buffer((GstAppSink*)pAppSink);
pStructure =gst_caps_get_structure(GST_CAPS(pBuffer->caps), 0);
gst_structure_get_int(pStructure, "width", &width);
gst_structure_get_int(pStructure, "height", &height);
gst_structure_get_int(pStructure, "bpp", &bpp);
printf("width = %d, height = %d\n", width, height);
printf("bpp= %d\n", bpp);
printf("\nsize = %d\n",GST_BUFFER_SIZE(pBuffer));
BMPwriter(GST_BUFFER_DATA(pBuffer),bpp, width, height, "out.bmp");
gst_buffer_unref (pBuffer);
g_main_loop_quit (pLoop);
}
最後 不要忘了釋放資源:
g_main_loop_unref(pLoop);
gst_object_unref(pAppSink);
gst_object_unref(pColorspace);
gst_object_unref(pJpegDecoder);
gst_object_unref(pSrcElement);
gst_object_unref (pPipeline);
參考
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-plugins/html/gst-plugins-base-plugins-giostreamsrc.html
http://docs.gstreamer.com/display/GstSDK/Basic+tutorial+8:+Short-cutting+the+pipeline