Vlc for Android 全面阐述

http://blog.csdn.net/banketree/article/details/39575973


目录(?)[+]

简介

Vlc for android是一款开源安卓播放器,具备播放多媒体文件、光盘、设备以及网络流媒体协议等功能,支持ARMv7 CPU或一个x86 CPU的设备,所有播放控制特性都已经开发完整。

下面将介绍如何获取代码、编译、vlc原理、缩小延迟、添加截图和录制视频、多路播放等。


详解
1、获取代码

官网源码下载:http://mirror.us.leaseweb.NET/videolan/

Git获取:clone from git://git.videolan.org/vlc-ports/Android.git

补丁:https://patches.videolan.org/

2、编译

1、搭配环境
AndroidSDK:adt-bundle-Linux-x86-20130522
JDK:jdk-7u25-linux-i586
NDK:android-ndk-r8e-linux-x86


2、安装工具
apt-get install gcc
apt-get install g++
apt-get build-dep vlc 
apt-get install git 
apt-get install wget 
apt-get install autoconf
apt-get install libtool
apt-get install subversion 
apt-get install cmake
apt-get install ant


3、配置信息

export ANDROID_NDK=/home/mythou/android-dev/android-ndk-r8e
export NDKR5C=/home/mythou/ndkr5c
export NDKR6B=/home/mythou/ndkr6b
PATH=$PATH:$NDKR6B:$ANDROID_NDK

export ANDROID_ABI=armeabi-v7a

export JAVA_HOME=/home/mythou/android-dev/jdk/jdk1.7.0_25
export JRE_HOME=/home/mythou/android-dev/jdk/jdk1.7.0_25/jre
export CLASSPATH=.:$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export ANT_HOME=/home/mythou/android-dev/apache-ant-1.8.0
export PATH=$JAVA_HOME/bin:$JAVA_HOME/jre/bin:$PATH:$HOME/bin:$ANT_HOME

export ANDROID_SDK=/home/mythou/android-dev/adt-bundle-linux-x86-20130522/sdk
PATH=$PATH:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools


4、编译

sh compile.sh   or    sh compile.sh release


5、辅助库

由于某些原因,有些库无法获得,请手动下载放入便可。

3、vlc播放原理

视频播放的基本步骤:
    1、acess 访问(获取视频数据)
    2、demux 解复用(音频、视频分离)  
    3、decode 解码(音频和视频的解码)
    4、output 输出(音频和视频的输出(aout和vout)


如图:


4、缩小延迟

修改延迟的方法有两种:1、直接用Java代码实现;2、在vlc库中修改。

涉及延迟的参数有:file-caching(文件缓存)、live-caching(直播缓存)、network-caching(网络缓存)、sout-mux-caching(输出缓存)。


Java代码实现如下:

[java]  view plain  copy
  1. options.add(":file-caching=1500");//文件缓存  
  2. options.add(":network-caching=1500");//网络缓存  
  3.   
  4. options.add(":live-caching=1500");//直播缓存  
  5. options.add(":sout-mux-caching=1500");//输出缓存  
  6.   
  7. options.add(":codec=mediacodec,iomx,all");  

vlc库实现如下:

查找目标文件vlc/src/libvlc-module.c  修改对应的参数

[java]  view plain  copy
  1. add_integer( "file-caching", DEFAULT_PTS_DELAY / 3000,  
  2.              CACHING_TEXT, CACHING_LONGTEXT, true )  
  3. add_integer( "live-caching", DEFAULT_PTS_DELAY / 3000,  
  4.              CAPTURE_CACHING_TEXT, CAPTURE_CACHING_LONGTEXT, true )  
  5. add_integer( "network-caching", CLOCK_FREQ / 3000,  
  6.              NETWORK_CACHING_TEXT, NETWORK_CACHING_LONGTEXT, true )  
  7. add_integer( "sout-mux-caching"1000, SOUT_MUX_CACHING_TEXT,  
  8.                             SOUT_MUX_CACHING_LONGTEXT, true )  

把分母数据增大,缓存的数据就越小,延迟就减少,流畅性就减少,相反,分母数据减少,缓存的数据就越大,延迟就增加,流畅性就增加。

测试结果,延迟明显减少。

5、添加截图和录制视频

官方已给出补丁实现截图和录制视频

1、截图

修改文件: android/configure.sh  搜索内容 -disable-sout   并删除

修改文件:android/vlc/contrib/src/ffmpeg/rules.mak  增加-enable-encoder=png的编码器 实现png格式截图

[java]  view plain  copy
  1. FFMPEGCONF += --disable-encoders --disable-muxers  
  2.  改成FFMPEGCONF += --disable-encoders --enable-encoder=png --disable-muxers  

源码重新编译便可

编译过程中可能会出现如下问题:

[java]  view plain  copy
  1. ./vlc/android/modules/.libs/libvorbis_plugin.a(libvorbis_plugin_la-vorbis.o): in function OpenEncoder:../../modules/codec/vorbis.c:758: error: undefined reference to 'vorbis_encode_setup_vbr‘  
解决方法:
修改文件  vlc-android/jni/Android.mk

[java]  view plain  copy
  1.  LOCAL_LDLIBS := -L$(VLC_CONTRIB)/lib \    
  2.     $(VLC_MODULES) \    
  3.     $(VLC_BUILD_DIR)/lib/.libs/libvlc.a \    
  4.     $(VLC_BUILD_DIR)/src/.libs/libvlccore.a \    
  5.     $(VLC_BUILD_DIR)/compat/.libs/libcompat.a \    
  6.     -ldl -lz -lm -llog \    
  7.     -ldvbpsi -lebml -lmatroska -ltag \    
  8.     -logg -lFLAC -ltheora -lvorbis -lvorbisfile -lvorbisenc \    
  9.     -lmpeg2 -la52 \    
  10.     -lavformat -lavcodec -lswscale -lavutil -lpostproc -lgsm -lopenjpeg \    
  11.     -lliveMedia -lUsageEnvironment -lBasicUsageEnvironment -lgroupsock \    
  12.     -lspeex -lspeexdsp \    
  13.     -lxml2 -lpng -lgnutls -lgcrypt -lgpg-error \    
  14.     -lnettle -lhogweed -lgmp \    
  15.     -lfreetype -liconv -lass -lfribidi -lopus \    
  16.     -lEGL -lGLESv2 -ljpeg \    
  17.     $(CPP_STATIC)    
  18.   
  19. 在  
  20. -logg -lFLAC -ltheora -lvorbis   
  21. 后添加  
  22. -lvorbisfile -lvorbisenc   

[java]  view plain  copy
  1. error: undefined reference to 'vlc_entry__access_output_udp'  
解决方法:
修改文件: /vlc/modules/access_output/ Modules.am

[java]  view plain  copy
  1. SOURCES_access_output_dummy = dummy.c    
  2.     SOURCES_access_output_file = file.c    
  3.     SOURCES_access_output_udp = udp.c    
  4.     SOURCES_access_output_http = http.c bonjour.c bonjour.h    
  5.     SOURCES_access_output_shout = shout.c    
  6.         
  7.         
  8.     access_output_LTLIBRARIES += \    
  9.         libaccess_output_dummy_plugin.la \    
  10.         libaccess_output_file_plugin.la \    
  11.         libaccess_output_udp_plugin.la \    
  12.         libaccess_output_http_plugin.la    
  13.         
  14.         
  15.     #libaccess_output_udp_plugin_la_SOURCES = udp.c    
  16.     #libaccess_output_udp_plugin_la_LIBADD = $(SOCKET_LIBS) $(LIBPTHREAD)    
  17.     #access_output_LTLIBRARIES += libaccess_output_udp_plugin.la    
  18.         
  19.         
  20.     libaccess_output_livehttp_plugin_la_SOURCES = livehttp.c    
  21.     libaccess_output_livehttp_plugin_la_CFLAGS = $(AM_CFLAGS) $(GCRYPT_CFLAGS)    
  22.     libaccess_output_livehttp_plugin_la_LIBADD = $(GCRYPT_LIBS) -lgpg-error    
  23.     if HAVE_GCRYPT    
  24.     access_output_LTLIBRARIES += libaccess_output_livehttp_plugin.la    
  25.     endif    
  26.   
  27. 内容覆盖便可  


相关源码添加:

在libvlcjni.c中增加函数:

[java]  view plain  copy
  1. boolean Java_org_videolan_libvlc_LibVLC_takeSnapShot(JNIEnv *env, jobject thiz,jint number, jstring path, jint width,jint height)    
  2. {    
  3.     jboolean isCopy;    
  4.    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);    
  5.      /* Get C string */    
  6.    const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);    
  7.     
  8.    if (mp)    
  9.         if(libvlc_video_take_snapshot(mp, (int)number,psz_path , (int)width,(int)height)==0)    
  10.             return JNI_TRUE;    
  11.    return JNI_FALSE;    
  12.     
  13. }    

LibVlc.java中增加native函数的接口和调用方法:

[java]  view plain  copy
  1. private native boolean takeSnapShot( int num, String file, int width, int height);    
[java]  view plain  copy
  1. public boolean takeSnapShot(String file, int width, int height) {    
  2.     return takeSnapShot(0, file, width, height);    
  3. }   

2、录制视频

录制补丁  https://patches.videolan.org/patch/606/

补丁内容如下:

[java]  view plain  copy
  1. diff --git a/include/vlc/libvlc_events.h b/include/vlc/libvlc_events.h  
  2. index 2cfedbf..25a16ea 100644  
  3. --- a/include/vlc/libvlc_events.h  
  4. +++ b/include/vlc/libvlc_events.h  
  5. @@ -72,6 +72,8 @@ enum libvlc_event_e {  
  6.      libvlc_MediaPlayerSnapshotTaken,  
  7.      libvlc_MediaPlayerLengthChanged,  
  8.      libvlc_MediaPlayerVout,  
  9. +    libvlc_MediaPlayerRecordableChanged,  
  10. +    libvlc_MediaPlayerRecordingFinished,  
  11.    
  12.      libvlc_MediaListItemAdded=0x200,  
  13.      libvlc_MediaListWillAddItem,  
  14. @@ -165,6 +167,14 @@ typedef struct libvlc_event_t  
  15.          } media_player_pausable_changed;  
  16.          struct  
  17.          {  
  18. +            int new_recordable;  
  19. +        } media_player_recordable_changed;  
  20. +        struct  
  21. +        {  
  22. +            char *psz_filename;  
  23. +        } media_player_recording_finished;  
  24. +        struct  
  25. +        {  
  26.              int new_count;  
  27.          } media_player_vout;  
  28.    
  29. diff --git a/include/vlc/libvlc_media_player.h b/include/vlc/libvlc_media_player.h  
  30. index aefef02..8ddef37 100644  
  31. --- a/include/vlc/libvlc_media_player.h  
  32. +++ b/include/vlc/libvlc_media_player.h  
  33. @@ -1628,6 +1628,121 @@ LIBVLC_API int libvlc_audio_set_delay( libvlc_media_player_t *p_mi, int64_t i_de  
  34.    
  35.  /** @} audio */  
  36.    
  37. +/** 
  38. + * Can the media player record the current media? 
  39. + * 
  40. + * Media must be buffering or playing before it can be recorded. 
  41. + * 
  42. + * The media player event manager will emit a libvlc_MediaPlayerRecordableChanged event 
  43. + * when the recordable state changes after starting media playback. The event data will 
  44. + * describe the new recordable state, so invocation of this API method is not strictly 
  45. + * necessary to determine when recording can be started. 
  46. + * 
  47. + * A libvlc_MediaPlayerRecordableChanged event will not be emitted if the media is 
  48. + * stopped (notified by a libvlc_MediaPlayerStoppedEvent) or finishes normally (notified 
  49. + * by a libvlc_MediaPlayerFinished event). 
  50. + * 
  51. + * A calling application should therefore register an event callback for those events 
  52. + * so that it may query the new recordable state and manage recording at the appropriate 
  53. + * time. 
  54. + * 
  55. + * \param p_mi media player 
  56. + * \return true if the media player can record, false if it can not 
  57. + * \version LibVLC 2.1.0 or later 
  58. + */  
  59. +LIBVLC_API bool libvlc_media_player_is_recordable( libvlc_media_player_t *p_mi );  
  60. +  
  61. +/** 
  62. + * Is the current media being recorded? 
  63. + * 
  64. + * \param p_mi media player 
  65. + * \return true if recording, false if not 
  66. + * \version LibVLC 2.1.0 or later 
  67. + */  
  68. +LIBVLC_API bool libvlc_media_player_is_recording( libvlc_media_player_t *p_mi );  
  69. +  
  70. +/** 
  71. + * Start recording the current media. 
  72. + * 
  73. + * Media must be buffering or playing before it can be recorded. A calling application 
  74. + * can begin recording immediately on receipt of a libvlc_MediaPlayerRecordableChanged 
  75. + * event sent via the media player event manager (if recording is possible for the 
  76. + * currently playing media), and any time thereafter until the media stops. 
  77. + * 
  78. + * Media will be saved to the file path denoted by the psz_filename parameter if it is 
  79. + * supplied. Any such supplied filename should not include a file extension as the 
  80. + * correct file extension will automatically be appended when the file is created. This 
  81. + * filename may denote a full path name, but each directory in the path must already 
  82. + * exist or recording will silently fail. If the calling application chooses to specify 
  83. + * the filename then it is the responsibility of that application to take account of 
  84. + * this and itself make sure any needed directories are created. 
  85. + * 
  86. + * Alternatively, a calling application need not supply a filename and so instead let 
  87. + * vlc automatically generate a unique filename. This will cause vlc to create a new 
  88. + * file in the appropriate media directory for the user - for example "~/Videos". The 
  89. + * actual filename used will be sent in an event when the recording is complete. 
  90. + * 
  91. + * When recording has finished and the new file has been completely saved, a 
  92. + * libvlc_MediaPlayerRecordingFinished event will be sent via the media player event 
  93. + * manager. The event data will contain the filename of the newly recorded file - this 
  94. + * will either be the filename as specified by the calling application or a filename 
  95. + * generated by vlc if the application did not supply a filename. In either case, this 
  96. + * filename will include the automatically appended file extension. 
  97. + * 
  98. + * The saved media file will not be immediately available or visible until recording 
  99. + * has completely finished and the libvlc_MediaPlayerRecordingFinished event has been 
  100. + * received, or the media has stopped or finished normally. 
  101. + * 
  102. + * Recording can be stopped and started on-the-fly once the recordable state is set; 
  103. + * each time recording is stopped and restarted a new file will be created so a calling 
  104. + * application should take care to provide unique filenames, or defer to vlc to create 
  105. + * unique filenames. 
  106. + * 
  107. + * Recording will be stopped when the media stops playing, and must be explicitly 
  108. + * started again to restart recording, i.e. the recording state is not automatically 
  109. + * preserved when playing media subsequently. 
  110. + * 
  111. + * Media player functionailty such as next/previous chapter, set time or position and 
  112. + * so on are ineffective when recording is enabled. However, pausing the media is 
  113. + * possible and will pause the recording; unpausing the media will resume playback and 
  114. + * recording. 
  115. + * 
  116. + * Recording of the primary media or sub-items is possible. 
  117. + * 
  118. + * \param p_mi media player 
  119. + * \param psz_filename name of the file to save the media to, not including any file extension, 
  120. + *                     or NULL if vlc should generate the filename automatically 
  121. + * \return 0 if recording was started, -1 on error 
  122. + * \version LibVLC 2.1.0 or later 
  123. + */  
  124. +LIBVLC_API int libvlc_media_player_record_start( libvlc_media_player_t *p_mi, const char *psz_filename );  
  125. +  
  126. +/** 
  127. + * Stop recording the current media. 
  128. + * 
  129. + * This method requests that the recording stop, and will return immediately. Recording 
  130. + * will not stop immediately. 
  131. + * 
  132. + * When the recording actually stops some short time later and the new file has 
  133. + * finished being written, a libvlc_MediaPlayerRecordingFinished event will be sent via 
  134. + * the media player event manager. The newly recorded file will not be visible or 
  135. + * available until after this event has been sent. 
  136. + * 
  137. + * The event data will contain the full name of the file that was created. The filename 
  138. + * will either be that as was specified by the calling application on invoking 
  139. + * libvlc_media_player_record_start(), or the filename that vlc automatically generated 
  140. + * if the calling application did not supply its own filename. In either case the 
  141. + * filename will contain the automatically appended file extension. 
  142. + * 
  143. + * There is no need to invoke this method to stop the recording if the media is stopped 
  144. + * or finishes playing normally. 
  145. + * 
  146. + * \param p_mi media player 
  147. + * \return 0 if recording was stopped, -1 on error 
  148. + * \version LibVLC 2.1.0 or later 
  149. + */  
  150. +LIBVLC_API int libvlc_media_player_record_stop( libvlc_media_player_t *p_mi );  
  151. +  
  152.  /** @} media_player */  
  153.    
  154.  # ifdef __cplusplus  
  155. diff --git a/lib/event.c b/lib/event.c  
  156. index c71a48a..7ef4abd 100644  
  157. --- a/lib/event.c  
  158. +++ b/lib/event.c  
  159. @@ -279,6 +279,8 @@ static const event_name_t event_list[] = {  
  160.      DEF(MediaPlayerSnapshotTaken)  
  161.      DEF(MediaPlayerLengthChanged)  
  162.      DEF(MediaPlayerVout)  
  163. +    DEF(MediaPlayerRecordableChanged)  
  164. +    DEF(MediaPlayerRecordingFinished)  
  165.    
  166.      DEF(MediaListItemAdded)  
  167.      DEF(MediaListWillAddItem)  
  168. diff --git a/lib/libvlc.sym b/lib/libvlc.sym  
  169. index 42dad5c..3ff67ef 100644  
  170. --- a/lib/libvlc.sym  
  171. +++ b/lib/libvlc.sym  
  172. @@ -137,6 +137,8 @@ libvlc_media_player_get_title  
  173.  libvlc_media_player_get_title_count  
  174.  libvlc_media_player_get_xwindow  
  175.  libvlc_media_player_has_vout  
  176. +libvlc_media_player_is_recordable  
  177. +libvlc_media_player_is_recording  
  178.  libvlc_media_player_is_seekable  
  179.  libvlc_media_player_is_playing  
  180.  libvlc_media_player_new  
  181. @@ -146,6 +148,8 @@ libvlc_media_player_set_pause  
  182.  libvlc_media_player_pause  
  183.  libvlc_media_player_play  
  184.  libvlc_media_player_previous_chapter  
  185. +libvlc_media_player_record_start  
  186. +libvlc_media_player_record_stop  
  187.  libvlc_media_player_release  
  188.  libvlc_media_player_retain  
  189.  libvlc_media_player_set_agl  
  190. diff --git a/lib/media_player.c b/lib/media_player.c  
  191. index a41b8c7..6573197 100644  
  192. --- a/lib/media_player.c  
  193. +++ b/lib/media_player.c  
  194. @@ -64,6 +64,10 @@ input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd,  
  195.                          vlc_value_t oldval, vlc_value_t newval,  
  196.                          void * p_userdata );  
  197.  static int  
  198. +input_recordable_changed( vlc_object_t *p_this, char const *psz_cmd,  
  199. +                          vlc_value_t oldval, vlc_value_t newval,  
  200. +                          void *p_userdata );  
  201. +static int  
  202.  input_event_changed( vlc_object_t * p_this, char const * psz_cmd,  
  203.                       vlc_value_t oldval, vlc_value_t newval,  
  204.                       void * p_userdata );  
  205. @@ -72,6 +76,10 @@ static int  
  206.  snapshot_was_taken( vlc_object_t *p_this, char const *psz_cmd,  
  207.                      vlc_value_t oldval, vlc_value_t newval, void *p_data );  
  208.    
  209. +static int  
  210. +file_recording_finished( vlc_object_t *p_this, char const *psz_cmd,  
  211. +                         vlc_value_t oldval, vlc_value_t newval, void *p_data );  
  212. +  
  213.  static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi );  
  214.    
  215.  /* 
  216. @@ -132,6 +140,8 @@ static void release_input_thread( libvlc_media_player_t *p_mi, bool b_input_abor 
  217.                       input_seekable_changed, p_mi ); 
  218.      var_DelCallback( p_input_thread, "can-pause", 
  219.                      input_pausable_changed, p_mi ); 
  220. +    var_DelCallback( p_input_thread, "can-record", 
  221. +                     input_recordable_changed, p_mi ); 
  222.      var_DelCallback( p_input_thread, "intf-event", 
  223.                       input_event_changed, p_mi ); 
  224.   
  225. @@ -227,6 +237,25 @@ input_pausable_changed( vlc_object_t * p_this, char const * psz_cmd, 
  226.  } 
  227.   
  228.  static int 
  229. +input_recordable_changed( vlc_object_t *p_this, char const *psz_cmd, 
  230. +                          vlc_value_t oldval, vlc_value_t newval, 
  231. +                          void *p_userdata ) 
  232. +{ 
  233. +    VLC_UNUSED(p_this); 
  234. +    VLC_UNUSED(psz_cmd); 
  235. +    VLC_UNUSED(oldval); 
  236. + 
  237. +    libvlc_media_player_t *p_mi = p_userdata; 
  238. +    libvlc_event_t event; 
  239. + 
  240. +    event.type = libvlc_MediaPlayerRecordableChanged; 
  241. +    event.u.media_player_recordable_changed.new_recordable = newval.b_bool; 
  242. + 
  243. +    libvlc_event_send( p_mi->p_event_manager, &event ); 
  244. +    return VLC_SUCCESS; 
  245. +} 
  246. + 
  247. +static int 
  248.  input_event_changed( vlc_object_t * p_this, char const * psz_cmd, 
  249.                       vlc_value_t oldval, vlc_value_t newval, 
  250.                       void * p_userdata ) 
  251. @@ -357,6 +386,23 @@ static int snapshot_was_taken(vlc_object_t *p_this, char const *psz_cmd, 
  252.      return VLC_SUCCESS; 
  253.  } 
  254.   
  255. +static int file_recording_finished(vlc_object_t *p_this, char const *psz_cmd, 
  256. +                                   vlc_value_t oldval, vlc_value_t newval, void *p_data ) 
  257. +{ 
  258. +    VLC_UNUSED(p_this); 
  259. +    VLC_UNUSED(psz_cmd); 
  260. +    VLC_UNUSED(oldval); 
  261. + 
  262. +    libvlc_media_player_t *p_mi = p_data; 
  263. +    libvlc_event_t event; 
  264. + 
  265. +    event.type = libvlc_MediaPlayerRecordingFinished; 
  266. +    event.u.media_player_recording_finished.psz_filename = newval.psz_string; 
  267. + 
  268. +    libvlc_event_send(p_mi->p_event_manager, &event); 
  269. +    return VLC_SUCCESS; 
  270. +} 
  271. + 
  272.  static input_thread_t *find_input (vlc_object_t *obj) 
  273.  { 
  274.      libvlc_media_player_t *mp = (libvlc_media_player_t *)obj; 
  275. @@ -480,6 +526,10 @@ libvlc_media_player_new( libvlc_instance_t *instance ) 
  276.      var_Create (mp, "amem-set-volume", VLC_VAR_ADDRESS); 
  277.      var_Create (mp, "amem-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT); 
  278.      var_Create (mp, "amem-rate", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); 
  279. + 
  280. +    var_Create (mp, "recording-finished", VLC_VAR_STRING); 
  281. +    var_AddCallback (mp, "recording-finished", file_recording_finished, mp); 
  282. + 
  283.      var_Create (mp, "amem-channels", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT); 
  284.   
  285.      mp->p_md = NULL; 
  286. @@ -515,6 +565,9 @@ libvlc_media_player_new( libvlc_instance_t *instance ) 
  287.      register_event(mp, TitleChanged); 
  288.      register_event(mp, PausableChanged); 
  289.   
  290. +    register_event(mp, RecordableChanged); 
  291. +    register_event(mp, RecordingFinished); 
  292. + 
  293.      register_event(mp, Vout); 
  294.   
  295.      /* Snapshot initialization */  
  296. @@ -566,6 +619,8 @@ static void libvlc_media_player_destroy( libvlc_media_player_t *p_mi )  
  297.      var_DelCallback( p_mi->p_libvlc,  
  298.                       "snapshot-file", snapshot_was_taken, p_mi );  
  299.    
  300. +    var_DelCallback( p_mi, "recording-finished", file_recording_finished, p_mi );  
  301. +  
  302.      /* No need for lock_input() because no other threads knows us anymore */  
  303.      if( p_mi->input.p_thread )  
  304.          release_input_thread(p_mi, true);  
  305. @@ -732,12 +787,14 @@ int libvlc_media_player_play( libvlc_media_player_t *p_mi )  
  306.    
  307.      var_AddCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );  
  308.      var_AddCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );  
  309. +    var_AddCallback( p_input_thread, "can-record", input_recordable_changed, p_mi );  
  310.      var_AddCallback( p_input_thread, "intf-event", input_event_changed, p_mi );  
  311.    
  312.      if( input_Start( p_input_thread ) )  
  313.      {  
  314.          unlock_input(p_mi);  
  315.          var_DelCallback( p_input_thread, "intf-event", input_event_changed, p_mi );  
  316. +        var_DelCallback( p_input_thread, "can-record", input_recordable_changed, p_mi );  
  317.          var_DelCallback( p_input_thread, "can-pause", input_pausable_changed, p_mi );  
  318.          var_DelCallback( p_input_thread, "can-seek", input_seekable_changed, p_mi );  
  319.          vlc_object_release( p_input_thread );  
  320. @@ -1409,3 +1466,62 @@ void libvlc_media_player_next_frame( libvlc_media_player_t *p_mi )  
  321.          vlc_object_release( p_input_thread );  
  322.      }  
  323.  }  
  324. +  
  325. +bool libvlc_media_player_is_recordable( libvlc_media_player_t *p_mi )  
  326. +{  
  327. +    input_thread_t *p_input_thread;  
  328. +    bool b_can_record;  
  329. +  
  330. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  331. +    if( !p_input_thread )  
  332. +        return false;  
  333. +  
  334. +    b_can_record = var_GetBool( p_input_thread, "can-record" );  
  335. +  
  336. +    vlc_object_release( p_input_thread );  
  337. +    return b_can_record;  
  338. +}  
  339. +  
  340. +bool libvlc_media_player_is_recording( libvlc_media_player_t *p_mi )  
  341. +{  
  342. +    input_thread_t *p_input_thread;  
  343. +    bool b_record;  
  344. +  
  345. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  346. +    if( !p_input_thread )  
  347. +        return false;  
  348. +  
  349. +    b_record = var_GetBool( p_input_thread, "record" );  
  350. +  
  351. +    vlc_object_release( p_input_thread );  
  352. +    return b_record;  
  353. +}  
  354. +  
  355. +int libvlc_media_player_record_start( libvlc_media_player_t *p_mi, const char* psz_filename )  
  356. +{  
  357. +    input_thread_t *p_input_thread;  
  358. +  
  359. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  360. +    if( !p_input_thread )  
  361. +        return -1;  
  362. +  
  363. +    var_SetString( p_input_thread, "input-record-path", psz_filename );  
  364. +    var_SetBool( p_input_thread, "record"true );  
  365. +  
  366. +    vlc_object_release( p_input_thread );  
  367. +    return 0;  
  368. +}  
  369. +  
  370. +int libvlc_media_player_record_stop( libvlc_media_player_t *p_mi )  
  371. +{  
  372. +    input_thread_t *p_input_thread;  
  373. +  
  374. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  375. +    if( !p_input_thread )  
  376. +        return -1;  
  377. +  
  378. +    var_SetBool( p_input_thread, "record"false );  
  379. +  
  380. +    vlc_object_release( p_input_thread );  
  381. +    return 0;  
  382. +}  
  383. diff --git a/modules/stream_out/record.c b/modules/stream_out/record.c  
  384. index de6d32e..40ddfea 100644  
  385. --- a/modules/stream_out/record.c  
  386. +++ b/modules/stream_out/record.c  
  387. @@ -110,6 +110,8 @@ struct sout_stream_sys_t  
  388.      int              i_id;  
  389.      sout_stream_id_t **id;  
  390.      mtime_t     i_dts_start;  
  391. +  
  392. +    char *psz_record_file;  
  393.  };  
  394.    
  395.  static void OutputStart( sout_stream_t *p_stream );  
  396. @@ -158,6 +160,8 @@ static int Open( vlc_object_t *p_this )  
  397.      p_sys->i_dts_start = 0;  
  398.      TAB_INIT( p_sys->i_id, p_sys->id );  
  399.    
  400. +    p_sys->psz_record_file = NULL;  
  401. +  
  402.      return VLC_SUCCESS;  
  403.  }  
  404.    
  405. @@ -172,6 +176,19 @@ static void Close( vlc_object_t * p_this )  
  406.      if( p_sys->p_out )  
  407.          sout_StreamChainDelete( p_sys->p_out, p_sys->p_out );  
  408.    
  409. +    if( p_sys->psz_record_file ) {  
  410. +        for( vlc_object_t *p_mp = p_stream->p_parent; p_mp; p_mp = p_mp->p_parent )  
  411. +        {  
  412. +            if( var_Type( p_mp, "recording-finished" ) )  
  413. +            {  
  414. +                var_SetString( p_mp, "recording-finished", p_sys->psz_record_file );  
  415. +                break;  
  416. +            }  
  417. +        }  
  418. +  
  419. +        free( p_sys->psz_record_file );  
  420. +    }  
  421. +  
  422.      TAB_CLEAN( p_sys->i_id, p_sys->id );  
  423.      free( p_sys->psz_prefix );  
  424.      free( p_sys );  
  425. @@ -352,7 +369,10 @@ static int OutputNew( sout_stream_t *p_stream,  
  426.      }  
  427.    
  428.      if( psz_file && psz_extension )  
  429. +    {  
  430. +        p_sys->psz_record_file = strdup( psz_file );  
  431.          var_SetString( p_stream->p_libvlc, "record-file", psz_file );  
  432. +    }  
  433.    
  434.      free( psz_file );  
  435.      free( psz_output );  
  436. diff --git a/src/input/var.c b/src/input/var.c  
  437. index 9613fe2..04f33b9 100644  
  438. --- a/src/input/var.c  
  439. +++ b/src/input/var.c  
  440. @@ -210,6 +210,9 @@ void input_ControlVarInit ( input_thread_t *p_input )  
  441.      text.psz_string = _("Subtitles Track");  
  442.      var_Change( p_input, "spu-es", VLC_VAR_SETTEXT, &text, NULL );  
  443.    
  444. +    /* ES Out */  
  445. +    var_Create( p_input, "input-record-path", VLC_VAR_STRING | VLC_VAR_DOINHERIT );  
  446. +  
  447.      /* Special read only objects variables for intf */  
  448.      var_Create( p_input, "bookmarks", VLC_VAR_STRING | VLC_VAR_DOINHERIT );  
  449.    

下载补丁,并把文件放到vlc目录中,执行命令patch -p1 < xxxx.patch,由于版本不一样有些地方会失败,请打开补丁自己检查手动修改。

补丁中主要相关函数:

[java]  view plain  copy
  1. +bool libvlc_media_player_is_recordable( libvlc_media_player_t *p_mi )  
  2. +{  
  3. +    input_thread_t *p_input_thread;  
  4. +    bool b_can_record;  
  5. +  
  6. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  7. +    if( !p_input_thread )  
  8. +        return false;  
  9. +  
  10. +    b_can_record = var_GetBool( p_input_thread, "can-record" );  
  11. +  
  12. +    vlc_object_release( p_input_thread );  
  13. +    return b_can_record;  
  14. +}  
  15. +  
  16. +bool libvlc_media_player_is_recording( libvlc_media_player_t *p_mi )  
  17. +{  
  18. +    input_thread_t *p_input_thread;  
  19. +    bool b_record;  
  20. +  
  21. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  22. +    if( !p_input_thread )  
  23. +        return false;  
  24. +  
  25. +    b_record = var_GetBool( p_input_thread, "record" );  
  26. +  
  27. +    vlc_object_release( p_input_thread );  
  28. +    return b_record;  
  29. +}  
  30. +  
  31. +int libvlc_media_player_record_start( libvlc_media_player_t *p_mi, const char* psz_filename )  
  32. +{  
  33. +    input_thread_t *p_input_thread;  
  34. +  
  35. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  36. +    if( !p_input_thread )  
  37. +        return -1;  
  38. +  
  39. +    var_SetString( p_input_thread, "input-record-path", psz_filename );  
  40. +    var_SetBool( p_input_thread, "record"true );  
  41. +  
  42. +    vlc_object_release( p_input_thread );  
  43. +    return 0;  
  44. +}  
  45. +  
  46. +int libvlc_media_player_record_stop( libvlc_media_player_t *p_mi )  
  47. +{  
  48. +    input_thread_t *p_input_thread;  
  49. +  
  50. +    p_input_thread = libvlc_get_input_thread( p_mi );  
  51. +    if( !p_input_thread )  
  52. +        return -1;  
  53. +  
  54. +    var_SetBool( p_input_thread, "record"false );  
  55. +  
  56. +    vlc_object_release( p_input_thread );  
  57. +    return 0;  
  58. +}  

库调用方法函数如下:

[java]  view plain  copy
  1. jboolean Java_org_videolan_libvlc_LibVLC_takeSnapShot(JNIEnv *env, jobject thiz,jint number, jstring path, jint width,jint height)    
  2. {    
  3.     jboolean isCopy;    
  4.    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);    
  5.      /* Get C string */    
  6.    const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);    
  7.     
  8.    if (mp)    
  9.         if(libvlc_video_take_snapshot(mp, (int)number,psz_path , (int)width,(int)height)==0)    
  10.             return JNI_TRUE;    
  11.    return JNI_FALSE;    
  12.     
  13. }    
  14.     
  15. jboolean Java_org_videolan_libvlc_LibVLC_videoRecordStart(JNIEnv *env, jobject thiz,jstring path)    
  16. {    
  17.     jboolean isCopy;    
  18.    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);    
  19.      /* Get C string */    
  20.    const char* psz_path = (*env)->GetStringUTFChars(env, path, &isCopy);    
  21.    //const char* psz_filename=(*env)->GetStringUTFChars(env, filename, &isCopy);    
  22.    if (mp)    
  23.         if(libvlc_media_player_record_start(mp,psz_path)==0)    
  24.             return JNI_TRUE;    
  25.    return JNI_FALSE;    
  26. }    
  27.     
  28. jboolean Java_org_videolan_libvlc_LibVLC_videoRecordStop(JNIEnv *env, jobject thiz)    
  29. {    
  30.     jboolean isCopy;    
  31.    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);    
  32.      /* Get C string */    
  33.    if (mp)    
  34.         if(libvlc_media_player_record_stop(mp)==0)    
  35.             return JNI_TRUE;    
  36.    return JNI_FALSE;    
  37. }    
  38.     
  39. jboolean Java_org_videolan_libvlc_LibVLC_videoIsRecording(JNIEnv *env, jobject thiz)    
  40. {    
  41.     jboolean isCopy;    
  42.    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);    
  43.    if (mp)    
  44.         if(libvlc_media_player_is_recording(mp))    
  45.             return JNI_TRUE;    
  46.    return JNI_FALSE;    
  47. }    
  48. jboolean Java_org_videolan_libvlc_LibVLC_videoIsRecordable(JNIEnv *env, jobject thiz)    
  49. {    
  50.     jboolean isCopy;    
  51.    libvlc_media_player_t *mp = getMediaPlayer(env, thiz);    
  52.    if (mp)    
  53.         if(libvlc_media_player_is_recordable(mp))    
  54.             return JNI_TRUE;    
  55.    return JNI_FALSE;    
  56. }    
  57.     
  58. jint Java_org_videolan_libvlc_LibVLC_getState(JNIEnv *env, jobject thiz)    
  59. {    
  60.     libvlc_media_player_t *mp = getMediaPlayer(env, thiz);    
  61.     if (mp){    
  62.         libvlc_state_t state=libvlc_media_player_get_state(mp);    
  63.         return (jint)state;    
  64.     }    
  65.     else    
  66.         return -1;    
  67. }  

6、实现多路播放

使用process属性实现



总结

接触vlc for android 是帮助朋友完成一个外单,即实现认证播放器的封装(即添加播放网络视频的认证),传地址便可播放。

经测试vlc无法播放swf文件,为了弥补这已缺陷,准备添加swfdec到android平台以支持swf文件。


推荐博客网站:http://flavienlaurent.com/

ndk_r11 (March 2016)
Windows 32-bit : http://dl.google.com/android/repository/android-ndk-r11-windows-x86.zip
Windows 64-bit : http://dl.google.com/android/repository/android-ndk-r11-windows-x86_64.zip
Mac OS X 64-bit : http://dl.google.com/android/repository/android-ndk-r11-darwin-x86_64.zip
Linux 64-bit (x86) : http://dl.google.com/android/repository/android-ndk-r11-linux-x86_64.zip



ndk_r10e (Jan 2015)









ndk_r10d (December 2014)









ndk_r10c(October 2014)









ndk_r10b(September 2014)










ndk_r10(July 2014)










ndk_r9d(March 2014)









ndk_r9c(December 2013)










ndk_r9b (October 2013)










ndk_r9 (July 2013)










ndk_r8e (March 2013)









Note :

NDK r8e is the first NDK with 32bit and 64bit releases. The prior ones were all 32bit and didn't have any suffix, so r8b would be:



ndk_r8d  (December 2012)






ndk_r8C   (November 2012)






ndk_r8b   (July 2012)






ndk_r8   (May 2012)






ndk_r7c (April 2012)







ndk_r7b (February 2012)







ndk_r7 (November 2011)







ndk_r6b (August 2011)







ndk_r6 (July 2011)







ndk_r5c  (June 2011)







ndk_r5b (January 2011)







ndk_r5 (December 2010)







ndk_r4b (June 2010)







ndk_r4 (may 2010)







ndk_r3 (March 2010)





8
3
 
 
猜你在找
机器学习之概率与统计推断
机器学习之数学基础
机器学习之凸优化
机器学习之矩阵
响应式布局全新探索
探究Linux的总线、设备、驱动模型
深度学习基础与TensorFlow实践
深度学习之神经网络原理与实战技巧
前端开发在线峰会
TensorFlow实战进阶:手把手教你做图像识别应用
查看评论
13楼  fwang313 2017-03-22 10:17发表 [回复]
楼主 你是ubuntu多少的呀,我的ubuntu16编译好多问题
12楼  goldenteny 2016-10-27 23:01发表 [回复]
楼主您好,
请教一个问:我下载的vlc-android怎么找不到稳重分析的关于access部分,比如里面提到的SOURCES_access_output_udp = udp.c ,我在几个版本的vlc-android版本中都找不到,请问您用的那个版本?可否给我共享,非常感谢!
我的QQ65461352
11楼  聪明的一休爱编程 2016-08-12 16:13发表 [回复]
options.add(":live-caching=1500");//直播缓存 options是来自哪个类,在哪个类中设置?
10楼  Dawish_大D 2016-06-09 14:39发表 [回复]
博主辛苦
9楼  码大哈 2015-09-10 12:26发表 [回复]
你好楼主,修改了rules.mak文件后重新运行 compile.sh发现ffmpeg并没有重新编译,该怎么处理?谢谢
8楼  icyttea 2015-07-13 15:35发表 [回复]
学习了 
尝试在Ubuntu14.0.4 下编译最新的VLC,总是出现arm-linux-androideabi-gcc -V不能识别的错误 无法通过编译
楼主可以分享一份编译好的.so 库吗? 太感谢了!
915896649@qq.com
7楼  icyttea 2015-06-12 10:40发表 [回复]
很赞,学习了
6楼  flcz163 2015-03-10 17:56发表 [回复]
麻烦问一下,最后那个多路播放“使用process属性实现”,是什么意思,麻烦你能说一下吗?
5楼  txm6355754 2015-02-12 10:42发表 [回复]
修改这些参数,options.add(":live-caching=1500")
减少,会有一个问题,就是在出现卡吨后,又会回到1500的延迟。请问有遇到过吗?怎么解喔!
4楼  lishihong108 2015-02-04 11:10发表 [回复]
[python]  view plain  copy
  1. 挡风  
3楼  pursuit 2014-12-10 14:58发表 [回复]
您好,博主:
我也想问这个问题:
文章中写到可以直接用Java代码实现 
options.add(":network-caching=1500");//网络缓存 
options是来自哪个类?百度不到.谢谢!
2楼  _ChrisKyle 2014-11-04 11:49发表 [回复]
您好 博主 : 最新我也在研究vlc这个框架 有些地方不太懂 能加下好友 请教一下吗 : QQ 7700131
1楼  cuiran 2014-10-08 21:25发表 [回复] [引用] [举报]
你好 想问下你接触过用vlc-android播放UDP 组播吗?我在使用vlc android时候播放 声音不是很顺畅 会出现卡顿
Re:  半棵树 2014-10-09 07:58发表 [回复] [引用] [举报]
回复cuiran:把缓存值提高增加流畅。
Re:  cuiran 2014-10-13 18:01发表 [回复] [引用] [举报]
回复半棵树:你好,看你文章中写到可以直接用Java代码实现 options.add(":live-caching=1500");//直播缓存 options是来自哪个类,谢谢!
Re:  djstavaV 2016-10-20 11:11发表 [回复]
回复cuiran:libvlc/src/org/videolan/libvlc/LibVLC/LibVLC.java






  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值