gstreamer移植qnx(四):交叉編譯qnx版本的gstreamer插件庫

一、簡介

​ 要移植gstreamer到qnx系統,除了本身的libgstreamer之外,還需要編譯相關的插件庫,比如編解碼庫,比如各種音視頻容器庫。

二、 編譯plugin base 庫

​ 這裏筆者一開始使用的和libgstreamer庫一樣,使用configure的方式,寫一個myconfig.sh來編譯,但是發現編譯出來的plugin library會帶有rpath的硬依賴路徑,因此這裏嘗試了另一種方式, 和編譯glib一樣,使用meson交叉編譯,寫一個qnx_arm.txt的 cross file文件,其內容如下:

[host_machine]
system = 'qnx'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'

[binaries]
c = 'arm-unknown-nto-qnx6.6.0eabi-gcc'
cpp = 'arm-unknown-nto-qnx6.6.0eabi-g++'
ar = 'arm-unknown-nto-qnx6.6.0eabi-ar'
strip = 'arm-unknown-nto-qnx6.6.0eabi-strip'
pkgconfig  = 'pkg-config'

[properties]
c_args = ['-D_QNX_SOURCE=1']
c_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
               '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0', '-lffi']
cpp_args = ['-D_QNX_SOURCE=1']
cpp_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
                 '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0', '-lffi']

[paths]
prefix = '/media/guwen/workspace/project/gstreamer/out'

​ 除了cross file文件之外,還需要修改 meson.build文件,其修改部分如下:

   default_options : [ 'warning_level=1',
                      'buildtype=release', # 修改編譯類型爲release 
                      'gtk_doc=disabled',  # 禁用gtk_doc 
                      'alsa=disabled',     # 禁用alsa 
                      'x11=disabled',      # 禁用x11 
                      'pango=disabled',    # 禁用pango 
                      'orc=disabled'       # 禁用orc 
                     ])

​ 另外,還需要設置pkg config 的路徑:

export PKG_CONFIG_LIBDIR=/media/guwen/workspace/project/gstreamer/out/lib/pkgconfig

注: 若果設置成了

export PKG_CONFIG_PATH=/media/guwen/workspace/project/gstreamer/out/lib/pkgconfig

就必須要在再設置PKG_CONFIG_LIBDIR, 因爲如果只設置了PKG_CONFIG_PATH路徑, pkg-config在這個路徑搜索之後,再到PKG_CONFIG_LIBDIR(這個就會是寄主系統默認路徑,Ubuntu的/usr/lib/pkgconfig等等)這個路徑搜索, 因此一定要設置PKG_CONFIG_LIBDIR變量,以防止pkg-config到系統默認路徑去搜索。

接下來也就是配置,編譯,安裝:

mkdir build
cd build
meson .. --cross-file ../qnx_arm.txt
ninja
ninja install

三、編譯plugin good 庫

plugin good庫也是使用meson進行編譯的,首先是qnx_arm.txt這個cross file的編寫,其內容如下:

[host_machine]
system = 'qnx'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'


[binaries]
c = 'arm-unknown-nto-qnx6.6.0eabi-gcc'
cpp = 'arm-unknown-nto-qnx6.6.0eabi-g++'
ar = 'arm-unknown-nto-qnx6.6.0eabi-ar'
strip = 'arm-unknown-nto-qnx6.6.0eabi-strip'
pkgconfig  = 'pkg-config'


[properties]
c_args = ['-D_QNX_SOURCE=1']
c_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
              '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0', '-lglib-2.0', '-lintl',  
              '-lffi']
cpp_args = ['-D_QNX_SOURCE=1']
cpp_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
                 '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0', '-lglib-2.0', '-lintl', 
                 '-lffi']

[paths]
prefix = '/media/guwen/workspace/project/gstreamer/out'

然後是meson.build修改:

  default_options : [ 'warning_level=1',
                      'buildtype=release', #修改編譯類型爲release
                      'c_std=gnu99',        #修改c語言標準爲99標準
                      'mpg123=enabled'      #使能mp3 audio decoder
                    ])

3.1 編譯mpg123

​ 首下載mpg123庫源碼 http://www.mpg123.de/download/mpg123-1.25.13.tar.bz2 ,這裏使用的是最新的1.25.13版本。

​ mpg123使用的也是configure,make的方式。 因此爲了方便,先編寫myconfig.sh腳本文件,其內容如下:

./configure --prefix=/media/guwen/workspace/project/gstreamer/out \
            --build=i686-linux --host=arm-unknown-nto-qnx6.6.0eabi

​ 接下來就是編譯和安裝:

make
make install

3.2 修改編譯錯誤

  • 修改源文件gst/flx/gstflxdec.c
/** 原始版本 882行 */
if (!flx_decode_chunks (flxdec, n_chunks, &chunks, &writer)) {
    GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
        ("%s", "Could not decode chunk"), NULL);
    goto unmap_input_error;
}
/////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if (!flx_decode_chunks (flxdec, n_chunks, &chunks, &writer)) {
    GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
        ("%s", "Could not decode chunk"), (NULL));
    goto unmap_input_error;
}

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

/** 原始版本 894行 */
out = gst_buffer_new_and_alloc (flxdec->size * 4);
 if (!gst_buffer_map (out, &map, GST_MAP_WRITE)) {
   GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
       ("%s", "Could not map output buffer"), NULL);
   gst_buffer_unref (out);
   goto unmap_input_error;
 }
/////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
out = gst_buffer_new_and_alloc (flxdec->size * 4);
 if (!gst_buffer_map (out, &map, GST_MAP_WRITE)) {
   GST_ELEMENT_ERROR (flxdec, STREAM, DECODE,
       ("%s", "Could not map output buffer"), (NULL));
   gst_buffer_unref (out);
   goto unmap_input_error;
 }


  • 修改文件 gst/multifile/gstsplitmuxsink.c
/** 原始版本 1564行 */
GST_ELEMENT_ERROR (splitmux, RESOURCE, SETTINGS,
      ("Could not create the new muxer/sink"), NULL);
}
/////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
GST_ELEMENT_ERROR (splitmux, RESOURCE, SETTINGS,
      ("Could not create the new muxer/sink"), (NULL));
}

/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

/** 原始版本 1753行 */
GST_ELEMENT_ERROR (splitmux, RESOURCE, SETTINGS,
       ("Could not create the new muxer/sink"), NULL);
}
/////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
GST_ELEMENT_ERROR (splitmux, RESOURCE, SETTINGS,
       ("Could not create the new muxer/sink"), (NULL));
}

  • 修改文件gst/rtp/gstrtpj2kdepay.c
/** 原始版本 211行 */
GST_ELEMENT_WARNING (depayload, STREAM, DEMUX, NULL,
     ("Non-compliant stream: sampling field missing. Frames my appear incorrect"));

/////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
GST_ELEMENT_WARNING (depayload, STREAM, DEMUX, (NULL),
     ("Non-compliant stream: sampling field missing. Frames my appear incorrect"));

3.3 編譯

和前面一樣,流程是一樣的:

export PKG_CONFIG_LIBDIR=/media/guwen/workspace/project/gstreamer/out/lib/pkgconfig
mkdir build
cd build
meson .. --cross-file ../qnx_arm.txt
ninja
ninja install

四、編譯plugin bad庫

​ qnx_arm.txt這個cross file的內容如下:

[host_machine]
system = 'qnx'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'


[binaries]
c = 'arm-unknown-nto-qnx6.6.0eabi-gcc'
cpp = 'arm-unknown-nto-qnx6.6.0eabi-g++'
ar = 'arm-unknown-nto-qnx6.6.0eabi-ar'
strip = 'arm-unknown-nto-qnx6.6.0eabi-strip'
pkgconfig  = 'pkg-config'


[properties]
c_args = ['-D_QNX_SOURCE=1']
c_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
               '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0','-lgstrtp-1.0', 
               '-lffi']
               
cpp_args = ['-D_QNX_SOURCE=1']
cpp_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
                 '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0','-lgstrtp-1.0', 
                 '-lffi']

[paths]
prefix = '/media/guwen/workspace/project/gstreamer/out'

meson.build 文件修改:

  default_options : [ 'warning_level=1',
                      'buildtype=release' ]) #修改編譯類型爲release

4.1 修改編譯錯誤

​ 和plugin good一樣,配置完成之後,編譯會有錯誤需要修正。

  • 修改文件gst/timecode/gstavwait.c
/** 原始版本 1128行 */
GST_ELEMENT_ERROR (self, CORE, FAILED,
       ("Failed to clip audio: it should have ended before the current segment"),
        NULL);
/////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
GST_ELEMENT_ERROR (self, CORE, FAILED,
       ("Failed to clip audio: it should have ended before the current segment"),
        (NULL));
  • 修改文件 gst/videoparsers/gstjpeg2000parse.c
/** 原始版本 354行 */
if (j2c_box_id_offset == -1) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
      ("Missing contiguous code stream box for j2c stream"));
  ret = GST_FLOW_ERROR;
  goto beach;
}

////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if (j2c_box_id_offset == -1) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, (NULL),
      ("Missing contiguous code stream box for j2c stream"));
  ret = GST_FLOW_ERROR;
  goto beach;
}

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

/** 原始版本 383行 */
if (j2c_box_id_offset + GST_JPEG2000_JP2_SIZE_OF_BOX_ID != magic_offset) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
      ("Corrupt contiguous code stream box for j2c stream"));
  ret = GST_FLOW_ERROR;
  goto beach;
}
////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if (j2c_box_id_offset + GST_JPEG2000_JP2_SIZE_OF_BOX_ID != magic_offset) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, (NULL),
      ("Corrupt contiguous code stream box for j2c stream"));
  ret = GST_FLOW_ERROR;
  goto beach;
}


////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

/** 原始版本 421行 */
if ((profile > GST_JPEG2000_PARSE_PROFILE_CINEMA_LTS)
    && !gst_jpeg2000_parse_is_broadcast (profile)
    && !gst_jpeg2000_parse_is_imf (profile)) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
      ("Unrecognized JPEG 2000 profile %d", profile));
  ret = GST_FLOW_ERROR;
  goto beach;
}

////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if ((profile > GST_JPEG2000_PARSE_PROFILE_CINEMA_LTS)
    && !gst_jpeg2000_parse_is_broadcast (profile)
    && !gst_jpeg2000_parse_is_imf (profile)) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, (NULL),
      ("Unrecognized JPEG 2000 profile %d", profile));
  ret = GST_FLOW_ERROR;
  goto beach;
}

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

/** 原始版本 434行 */
if (sub_level > 9) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
      ("Sub level %d is invalid", sub_level));
  ret = GST_FLOW_ERROR;
  goto beach;
}

////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if (sub_level > 9) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, (NULL),
      ("Sub level %d is invalid", sub_level));
  ret = GST_FLOW_ERROR;
  goto beach;
}

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

/** 原始版本 441行 */
if (validate_main_level && main_level > 11) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
      ("Main level %d is invalid", main_level));
  ret = GST_FLOW_ERROR;
  goto beach;
}
////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if (validate_main_level && main_level > 11) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, (NULL),
      ("Main level %d is invalid", main_level));
  ret = GST_FLOW_ERROR;
  goto beach;
}


////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

/** 原始版本 464行 */

/* sanity check on image dimensions */
if (x1 < x0 || y1 < y0) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
      ("Nonsensical image dimensions %d,%d,%d,%d", x0, y0, x1, y1));
  ret = GST_FLOW_ERROR;
  goto beach;
}
////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if (x1 < x0 || y1 < y0) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, (NULL),
      ("Nonsensical image dimensions %d,%d,%d,%d", x0, y0, x1, y1));
  ret = GST_FLOW_ERROR;
  goto beach;
}

////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////
/** 原始版本 484行 */
if (numcomps == 0 || numcomps > GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, NULL,
      ("Unsupported number of components %d", numcomps));
  ret = GST_FLOW_NOT_NEGOTIATED;
  goto beach;
}
////////////////////////////////////////////////////////////////////////////////////
/** 修改之後的版本 */  
if (numcomps == 0 || numcomps > GST_JPEG2000_PARSE_MAX_SUPPORTED_COMPONENTS) {
  GST_ELEMENT_ERROR (jpeg2000parse, STREAM, DECODE, (NULL),
      ("Unsupported number of components %d", numcomps));
  ret = GST_FLOW_NOT_NEGOTIATED;
  goto beach;
}

4.2 編譯 fdk-aac 庫

​ 不知道怎麼回事,gstreamer的libav插件好多decoder都不能正常使用,這裏我驗證用的mkv文件裏面音頻是aac格式的,結果用libav就匹配不了, 因此只能使用開源的fdk-acc庫,首先是配置的腳本文件:

./configure --prefix=/media/guwen/workspace/project/gstreamer/out \
            --host=arm-unknown-nto-qnx6.6.0eabi --disable-static

​ 然後再進行編譯安裝

make -j4
make install

4.3 編譯

和前面一樣,其過程如下:

export PKG_CONFIG_LIBDIR=/media/guwen/workspace/project/gstreamer/out/lib/pkgconfig
mkdir build
cd build
meson .. --cross-file ../qnx_arm.txt
ninja
ninja install

五、編譯gst-libav 庫

5.1 編譯FFmpeg

​ 首先是交叉編譯FFmpeg庫,第一步,編寫進行配置用的shell腳本文件myconfig.sh,其內容如下:

./configure --prefix=/media/guwen/workspace/project/gstreamer/out \
        --cross-prefix=arm-unknown-nto-qnx6.6.0eabi- \
        --enable-cross-compile \
        --pkg-config=pkg-config \
        --target-os=qnx \
        --cc=arm-unknown-nto-qnx6.6.0eabi-gcc \
        --arch=arm \
        --enable-shared \
        --disable-static \
        --enable-gpl \
        --enable-nonfree \
        --disable-armv5te \
        --disable-armv6 \
        --disable-armv6t2 \
        --disable-debug \
        --enable-neon \
        --extra-cflags="-std=gnu99 -fPIC" \
        --disable-programs \
        --disable-encoders \
        --disable-devices \
        --disable-muxers \
        --disable-decoders \
        --disable-demuxers \
        --disable-avdevice \
        --disable-bsfs \
        --disable-filters \
        --disable-doc \
        --enable-decoder=h264 \
        --enable-decoder=aac \
        --enable-decoder=ac3 \
        --enable-demuxer=mov \
        --enable-demuxer=mp3 \
        --enable-demuxer=matroska

這裏只enable了 h264 aac ac3 , mov, mp3, matroska 等幾個解碼器和容器,這樣既可以加快編譯速度,也可以減少生成lib的大小。

  • 修改編譯錯誤,文件libavformat/sctp.c

​ 這個文件的錯誤主要是因爲CMSG_SPACE這個宏來計算recvmsg和sendmsg的buffer size, 其錯誤原因,將這個計算出來的size,作爲一個數組的size,但CMSG_SPACE這個宏的實現裏面有一個是獲取align大小的函數__cmsg_alignbytes,因此就會報這樣的錯誤:

libavformat/sctp.c: In function ‘ff_sctp_recvmsg’:
libavformat/sctp.c:80:17: error: variable length array ‘incmsg’ is used [-Werror=vla]
libavformat/sctp.c: In function ‘ff_sctp_send’:
libavformat/sctp.c:131:22: error: variable length array ‘outcmsg’ is used [-Werror=vla]

​ 因此這裏需要自己實現CMSG_SPACE這個宏,在qnx的toolchain中,其定義如下:

/*
 * Alignment requirement for CMSG struct manipulation.
 * This basically behaves the same as ALIGN() ARCH/include/param.h.
 * We declare it separately for two reasons:
 * (1) avoid dependency between machine/param.h, and (2) to sync with kernel's
 * idea of ALIGNBYTES at runtime.
 * without (2), we can't guarantee binary compatibility in case of future
 * changes in ALIGNBYTES.
 */
#define __CMSG_ALIGN(n)	(((n) + __cmsg_alignbytes()) & ~__cmsg_alignbytes())
#define CMSG_SPACE(l)	(__CMSG_ALIGN(sizeof(struct cmsghdr)) + __CMSG_ALIGN(l))

​ 出現錯誤的原因就是因爲這裏的__cmsg_alignbytes是一個函數,其作用是獲取cmsg是按幾個字節對齊的,經過測試,這個函數的返回值爲7, 因此這裏實現的的宏如下所示:


/**爲了預防衝突,將CMSG_SPACE 修改爲  MY_CMSG_SPACE */
#define __MY_CMSG_ALIGN(n)	(((n) + 7) & ~7)
#define MY_CMSG_SPACE(l)	\
           (__MY_CMSG_ALIGN(sizeof(struct cmsghdr)) + __MY_CMSG_ALIGN(l))
  • 修改運行錯誤,文件libavutil/mem.c

​ 變了了FFMpeg4.2.1之後,在運行的時候發現在libavutil/eval.c文件的av_expr_parse_and_eval這個函數裏面調用av_expr_free這個函數時,會在最後av_freep(&e);這句的時候發生錯誤(併產生coredump), 一開始我以爲是發生了內存越界,但是通過在這段內存的前後都加上16字節的空餘空間,在av_freep(&e);這句之前打印是否存在內存越界,結果是,並沒有發生內存越界,更奇妙的是,這樣做之後也不會發生錯誤了。 在網上搜索了一下,發現qnx下的posix_memalign 和memalign這兩個函數似乎有問題, 因此這裏需要修改一下av_malloc函數的實現:

void *av_malloc(size_t size)
{
    void *ptr = NULL;

    /* let's disallow possibly ambiguous cases */
  if (size > (max_alloc_size - 32))
        return NULL;
 #if 0 /** 註釋掉原本的實現 */
#if HAVE_POSIX_MEMALIGN
	if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
    if (posix_memalign(&ptr, ALIGN, size))
        ptr = NULL;
#elif HAVE_ALIGNED_MALLOC
    ptr = _aligned_malloc(size, ALIGN);
#elif HAVE_MEMALIGN
#ifndef __DJGPP__
     ptr = memalign(ALIGN, size);
#else
     ptr = memalign(size, ALIGN);
#endif
    /* Why 64?
     * Indeed, we should align it:
     *   on  4 for 386
     *   on 16 for 486
     *   on 32 for 586, PPro - K6-III
     *   on 64 for K7 (maybe for P3 too).
     * Because L1 and L2 caches are aligned on those values.
     * But I don't want to code such logic here!
     */
    /* Why 32?
     * For AVX ASM. SSE / NEON needs only 16.
     * Why not larger? Because I did not see a difference in benchmarks ...
     */
    /* benchmarks with P3
     * memalign(64) + 1          3071, 3051, 3032
     * memalign(64) + 2          3051, 3032, 3041
     * memalign(64) + 4          2911, 2896, 2915
     * memalign(64) + 8          2545, 2554, 2550
     * memalign(64) + 16         2543, 2572, 2563
     * memalign(64) + 32         2546, 2545, 2571
     * memalign(64) + 64         2570, 2533, 2558
     *
     * BTW, malloc seems to do 8-byte alignment by default here.
     */
#else
    ptr = malloc(size);
#endif
#else /**使用普通的malloc來替代posix_memalign 或 memalign函數 */
    ptr = malloc(size);
#endif /** */
    
    if(!ptr && !size) {
        size = 1;
        ptr= av_malloc(1);
    }
#if CONFIG_MEMORY_POISONING
    if (ptr)
        memset(ptr, FF_MEMORY_POISON, size);
#endif
    return ptr;
  • 編譯過程

    make
    make install
    

5.2 準備gst-libav庫編譯腳本

  • 編寫meson的cross file 文件qnx_arm.txt

[host_machine]
system = 'qnx'
cpu_family = 'arm'
cpu = 'armv7'
endian = 'little'


[binaries]
c = 'arm-unknown-nto-qnx6.6.0eabi-gcc'
cpp = 'arm-unknown-nto-qnx6.6.0eabi-g++'
ar = 'arm-unknown-nto-qnx6.6.0eabi-ar'
strip = 'arm-unknown-nto-qnx6.6.0eabi-strip'
pkgconfig  = 'pkg-config'


[properties]
c_args = ['-D_QNX_SOURCE=1']
c_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
               '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0', '-lffi']
cpp_args = ['-D_QNX_SOURCE=1']
cpp_link_args = ['-lsocket', '-L/media/guwen/workspace/project/gstreamer/out/lib', 
                 '-lgobject-2.0', '-lgio-2.0', '-lgmodule-2.0', '-lffi']

[paths]
prefix = '/media/guwen/workspace/project/gstreamer/out'
  • 修改meson.build文件
 default_options : [ 'warning_level=1',
                     'buildtype=release' ]) #編譯 release版本
  • 新增mp3 demuxer支持

​ 我完成了所有編譯移植之後,原本想那個常見的音樂格式mp3文件進行測試,但發現,卻沒有找到支持mp3 格式的demuxer插件或元件。因此需要在gst-libav目錄裏面把對於mp3格式的支持放開。

  • 新增mkv demuxer支持,

​ 同樣,在進行視頻播放測試的時候,準備使用mkv格式的視頻進行播放,發現libgstmatroska.so這個插件,並不能支持我用於測試的常見的mkv文件,不知道爲什麼,於是就準備使用libav這個插件來進行支持。

​ 最終對gstavdemux.c文件中的的 gboolean gst_ffmpegdemux_register (GstPlugin * plugin)函數的修改內容如下所示:

   /* Don't use the typefind functions of formats for which we already have
     * better typefind functions */
    if (!strcmp (in_plugin->name, "mov,mp4,m4a,3gp,3g2,mj2") ||
        !strcmp (in_plugin->name, "ass") ||
        !strcmp (in_plugin->name, "avi") ||
        !strcmp (in_plugin->name, "asf") ||
        !strcmp (in_plugin->name, "mpegvideo") ||
        /*!strcmp (in_plugin->name, "mp3") || 
        !strcmp (in_plugin->name, "matroska") ||
        !strcmp (in_plugin->name, "matroska_webm") ||
        !strcmp (in_plugin->name, "matroska,webm") ||*/ //修改部分,放開mp3和mkv容器的限制
        !strcmp (in_plugin->name, "mpeg") ||
        !strcmp (in_plugin->name, "wav") ||
        
        /////////////////////////////////////////////////////////////////////
        
        !strcmp (in_plugin->name, "brstm") ||
        !strcmp (in_plugin->name, "bfstm") ||
        !strcmp (in_plugin->name, "gif") ||
		!strcmp (in_plugin->name, "mp3") || /**新增mp3容器支持 */
		!strcmp (in_plugin->name, "matroska") || /**新增mkv容器支持 */
		!strcmp (in_plugin->name, "matroska_webm") || /**新增mkv容器支持 */
        !strcmp (in_plugin->name, "matroska,webm") || /**新增mkv容器支持 */
        !strcmp (in_plugin->name, "dsf") || 
        !strcmp (in_plugin->name, "iff"))      
  • 另外,修正一個gstavdemux.c文件中的錯誤

​ 準確的說應該是完善, 在gstavdemux.c文件中gst_ffmpegdemux_type_find函數中需要通過plugin name作爲fromat名稱,來生成對應的sink pad的 caps信息, 但是在使用libav中的mkv容器時, 其形式爲 “matroska,webm”, 這樣gst_ffmpeg_formatid_to_caps中生成的caps就會將這個名稱看出兩個字段 “matroska” 和“webm", 也爲了避免這個問題,需要像其他地方一樣使用 g_strdelimit來將 ‘,’ 之類的符號替換爲’_’。 其具體修改如下所示:

/** 原始代碼 */
      sinkcaps = gst_ffmpeg_formatid_to_caps (in_plugin->name);

      GST_LOG ("libav typefinder '%s' suggests %" GST_PTR_FORMAT ", p=%u%%",
          in_plugin->name, sinkcaps, res);

      gst_type_find_suggest (tf, res, sinkcaps);
      gst_caps_unref (sinkcaps);

////////////////////////////////////////////////////////////////////////////
/** 修改後的代碼 */
      gchar* format_name = g_strdup(in_plugin->name); /** dup一份plugin的名稱 */
      g_strdelimit (format_name, ".,|-<> ", '_'); /** 將字符串中的 ',' 替換爲'_'  */

      sinkcaps = gst_ffmpeg_formatid_to_caps (format_name);  /** 生成sink caps */

      GST_LOG ("libav typefinder '%s' suggests %" GST_PTR_FORMAT ", p=%u%%",
          in_plugin->name, sinkcaps, res);

      gst_type_find_suggest (tf, res, sinkcaps);
      gst_caps_unref (sinkcaps);
      g_free(format_name);  /** 使用完之後,釋放掉dup來的字符串 */

5.3 編譯

export PKG_CONFIG_LIBDIR=/media/guwen/workspace/project/gstreamer/out/lib/pkgconfig
mkdir build
cd build
meson .. --cross-file ../qnx_arm.txt
ninja
ninja install

六、總結

其實編譯出來的不少插件,這裏都是沒有用到的,如果要精細編譯的話,就需要針對這些插件庫進行細緻的配置,明確的指定enable項。

另外 對於meson編譯方式,其實原則上不應該去修改 meson.build文件, 應該視同meson -Dxxx=xxx的方式, 這裏其實可以使用和configure編譯方式一樣的做法, 將運行meson 命令相關的內容寫到一個shell腳本文件裏面去。這樣每個項目就只需要新增qnx_arm.txt 和一個類似myconfig.sh的shell腳本。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章