以gstreamer從內存中讀入jpeg數據 解壓後 亦將結果輸出至內存

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




你可能感兴趣的:(以gstreamer從內存中讀入jpeg數據 解壓後 亦將結果輸出至內存)