gstreamer 1.0 初阶

# media framworks
opencore:
 begin with PacketVideo
 av sync with master clock
 sink-node
 parallel parser/decoder/sink
 dropped in android 2.3 (died)

stagefright:
 begin with android 2.1
 video sync with audio callback data's timestamp.
 callback and videoevent
 serial parser/decoder/sink

openMAX:
 begin with android 2.3
 fill buffer, empty buffer.

android.media.MediaCodec
 begin with android 4.1
 supported containers: mp4, 3gpp, and mkv
 cpp calls java: http://git.videolan.org/?p=vlc.git;a=tree;f=modules/codec/omxil

gstreamer:
 autoconnect pipeline components
 recognize input streams
 vaapisink get the raw yuv planes
 dmabuf
 use VPP for hwaccel transfers to dma_buf imported buffers

hardware optimization -- http://elinux.org/images/7/71/Elc2013_Matsubara.pdf
opengl experiences -- https://vec.io/posts/use-android-hardware-decoder-with-omxcodec-in-ndk
https://github.com/yixia/FFmpeg-Android/blob/master/FFmpeg-Android.sh
http://docs.gstreamer.com/display/GstSDK/Playback+tutorial+8%3A+Hardware-accelerated+video+decoding
http://gstreamer.freedesktop.org/data/pkg/android/1.6.2/gstreamer-1.0-android-armv7-1.6.2.tar.bz2
frameworks/av/include/media/stagefright/MediaSource.h
frameworks/av/media/libstagefright/OMXCodec.cpp
frameworks/av/include/media/stagefright/OMXCodec.h
AVCodec *codec = avcodec_find_decoder_by_name("libx265");


# gstreamer pipeline
pipeline > bin > element

data down:
gst_pad_push
gst_pad_pull_range

gst_buffer_new
gst_buffer_pool_acquire_buffer
buffer = {timestamp, offset, duration, metadata}

event up and down:

element states: NULL, READY, PAUSED, PLAYING

内部GST_MESSAGE_SEGMENT_DONE或pad连接后,设置GST_STATE_READY。
app设置NULL/PLAYING/PAUSED驱动pipeline。
只有preroll足够数据后,才能从READY转换到PAUSED,对于livesource例外。

construct pipeline:
gst_pipeline_new
READY_TO_PAUSED:
 gst_bin_add
 gst_pad_link

gst_pipeline_get_bus: src -- EOS -- sink -- EOS
gst_element_query: duration, total time.
gst_element_send_event
 sink -> SEEK --> FLUSH_START -> FLUSH -> SEGMENT, running_time = 0.

gst_pad_set_chain_function(audiosink)

gst-launch.c main -> gst_parse_launch (pipeline_string, &err);

# eg. overlay text on raw video
depends: freetype, harfbuzz/uniscribe/CoreText, cairo, pango (1999, Raph Levien -- Inconsolata).
videotestsrc ! video/x-raw,width=320,height=480,pixel-aspect-ratio=2/1 ! textoverlay text=Hello font-desc=72 ! xvimagesink
gst-launch \
    filesrc location=test.mpg \
      ! decodebin2 name=demuxer \
    demuxer. \
      ! textoverlay text=Hello \
      ! x264enc ! muxer. \
    demuxer. ! audioconvert ! vorbisenc ! muxer. \
    matro?skamux name=muxer \
      ! filesink location=output.mkv
vorbisenc to faac and matroskamux to mpegtsmux to get output.mpg
clockoverlay time-format="%H:%M:%S"
#changes the colors and adds scratches and dust
gst-launch-1.0 -m videotestsrc ! agingtv ! videoconvert ! autovideosink
gst-launch filesrc location=file.jpg ! jpegdec ! imagefreeze ! mfw_isink.

#debug output
in source code:
GST_DEBUG_CATEGORY (my_cat);
GST_DEBUG_CATEGORY_INIT (my_cat, "abcplugin", 0, "abcplugin");
GST_INFO(): 3 (NONE:0, ERROR:1, WARNING:2, DEBUG:4, LOG:5)

print <=3 of abcplugin, <=4 of yy prefix, <=2 of other plugins:
GST_DEBUG=2,abcplugin:3,yy*:4

# dump pipeline

in gst-launch:
export GST_DEBUG_DUMP_DOT_DIR=.
gst-launch audiotestsrc num-buffers=1000 ! fakesink sync=false

in source code:
compile without GST_DISABLE_GST_DEBUG
export GST_DEBUG_DUMP_DOT_DIR=.

GST_DEBUG_BIN_TO_DOT_FILE_TS(pipeline, GST_DEBUG_GRAPH_SHOW_ALL, "myout");

# write plugin
宏GST_PLUGIN_DEFINE用于定义一个plugin的入口点plugin_init和元数据。同时,它用于输出(export)一个plugin,这样它就就可以被其他应用程序使用。
例如:

static void init(void){
 gst_element_register(plugin, feature1_name);
}

GST_PLUGIN_DEFINE (
 GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    name,
    "my plugin description",

    init,
    VERSION,
    GST_LICENSE,
    GST_PACKAGE_NAME,
    GST_PACKAGE_ORIGIN)

GST_PLUGIN_DEFINE 根据GST_PLUGIN_BUILD_STATIC展开为静态形式:
void gst_plugin_name_register(void){
 gst_plugin_register_static(name, init);
}

或动态库形式(*.so):
GstPluginDesc gst_plugin_desc = {##name, init};

gst_registry_get()返回全局变量_gst_registry_default,init_post注册内置元件以及加载标准plugins(插件)。

gst_init -> gst_init_check -> init_post
 gst_object_get_type
 gst_element_get_type
 gst_bus_get_type
 gst_update_registry -> load_plugin_func

load_plugin_func(filename)
 gst_plugin_load_file
 gst_registry_add_plugin (gst_registry_get(), plugin)

gst_plugin_load_file(filename) -> _priv_gst_plugin_load_file_for_registry:
 module = g_module_open (GST_PLUGIN_PATH##filename, G_MODULE_BIND_LOCAL);
 g_module_symbol (module, "gst_plugin_desc", &ptr);
 desc = (GstPluginDesc *) ptr;
 GstPlugin *plugin = g_object_newv (GST_TYPE_PLUGIN, 0, NULL);
 return plugin;

gst_registry_add_plugin(registry, plugin):
 registry->priv->plugins = g_list_prepend (registry->priv->plugins, plugin);
 g_signal_emit (registry, gst_registry_signals[PLUGIN_ADDED], 0, plugin);
 gst_plugin_register_func -> init

gst_plugin_register_static
 GstPlugin *plugin = g_object_newv (GST_TYPE_PLUGIN, 0, NULL);
 gst_plugin_register_func -> init


# GLib Dynamic Type System
dynamic type system:  query for object metadata at runtime.
GTypeInfo:{base, class, instance, value_table}
constructor: base --> class --> instance
copy operatortor: value_table
destructor: dispose refs/finalize free: instance -> class -> base.

# G_DEFINE_TYPE(TN, t_n, T_P) 展开

static void t_n_class_init(TNClass *kclass);
static void t_n_init(TN *self);
static gpointer t_n_parent_class = NULL; //quizz: why need this?
Gtype t_n_get_type(void)
{
 static GType type = 0;
 if(type == 0){
  type = g_type_register_static_simple(T_P, "TN",
   sizeof(TNClass), t_n_class_init,
   sizeof(TN), t_n_init, 0);
 }
 return type;
}


/////////////property/////////////
继承关系:
element <- GST_TYPE_OBJECT <- gobject: G_TYPE_INITIALLY_UNOWNED=g_initially_unowned_get_type()

static void t_n_class_init(TNClass *kclass)
{
 GObjectClass *object_class = G_OBJECT_CLASS (klass);
 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
 object_class->set_property = set_property; //overwrite default
 object_class->get_property = get_property;
 //object_class->dispose(GObject *gobject);
 //object_class->finalize(GObject *gobject);
 

 pspec_add = g_param_spec_uint64 ("add", "Add", "Number of added samples",
      0, 4, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 g_object_class_install_property (object_class, PROP_ADD, pspec_add);

 element_class->change_state = change_state;
}

static void gst_audio_rate_set_property (GObject * object,
    guint prop_id, const GValue * value, GParamSpec * pspec)
{
 GstAudioRate *audiorate = GST_AUDIO_RATE (object);
 if(PROP_ADD == prop_id){
  
 }
}

static void change_state (GstElement * element, GstStateChange transition)
{
 GstAudioRate *audiorate = GST_AUDIO_RATE (element);
 if(GST_STATE_CHANGE_PAUSED_TO_READY == transition){
  //
 }
 return GST_ELEMENT_CLASS (t_n_parent_class)->change_state(element, transition);
}

g_signal_connect callback to events.

affect auto-plugger:
gst_plugin_feature_set_rank
 GST_RANK_PRIMARY+1 -- enable
 GST_RANK_NONE -- disable using this plugin

Static linking with re-locatable archives: -DPIC and -fPIC
 libgstreamer_android.so --whole-archive


# todo
gst_type_find_helper_get_range

/*
apt-get install libgstreamer1.0-dev libgstreamer-plugins-good1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev

gcc gst-hello.c -g $(pkg-config --cflags --libs  gstreamer-1.0)

GST_DEBUG="*:3" ./a.out

gst-inspect-1.0
 ...
 Total count: 196 plugins, 666 features

grep -nr 'gst_element_register' --include=*.c ./

gst-launch-1.0 playbin uri=file://$(pwd)/file.ogg

  gst-launch-1.0 filesrc location=file.ogg ! decodebin ! tee name=d  \
  d. ! queue ! audioconvert ! audioresample ! autoaudiosink \
  d. ! queue ! audioconvert ! monoscope ! videoconvert ! ximagesink \
  d. ! queue ! goom ! videoconvert ! xvimagesink

transcode:
gst-launch-1.0 filesrc location=out0.mp4 ! decodebin name=dmux ! queue ! audioconvert ! lamemp3enc ! filesink location=out.mp3

gst-launch-1.0 filesrc location=out0.mp4 ! decodebin name=dmux ! queue ! audioconvert ! lamemp3enc ! mux. dmux. ! queue ! x264enc ! mpegtsmux name=mux ! queue ! filesink location=out.ts

“! mux.” means link to mpegtsmux
lamemp3enc 需要安装 gstreamer1.0-plugins-ugly
h264 需要安装 gstreamer1.0-libav
转码后是h264+mp3,文件大小是原来的8倍!播放时发现视频dts < pts。
对比ffmpeg转码为mpeg2+mp2, 文件大小是原来的3倍。

 gst-launch-1.0 -v audiotestsrc ! goom ! videoconvert ! xvimagesink
 v4l2src

#ref
http://wiki.oz9aec.net/index.php/Gstreamer_cheat_sheet
http://gstreamer.freedesktop.org/documentation/

*/

#include 
  
int main(int argc, char *argv[]) {
  GstElement *pipeline;
  GstBus *bus;
  GstMessage *msg;
  
  /* Initialize GStreamer */
  gst_init (&argc, &argv);
  
  /* Build the pipeline */
  pipeline = gst_parse_launch ("playbin uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);
  if(!pipeline){	
	return -1;
  }
  
  /* Start playing */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  
  /* Wait until error or EOS */
  bus = gst_element_get_bus (pipeline);
  msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
  
  /* Free resources */
  if (msg != NULL)
    gst_message_unref (msg);
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}


 

 

你可能感兴趣的:(codec)