当前位置:   article > 正文

android 通过调用VLC的libvlcjni.so解码视频和rtsp流_android调用vlc.so库

android调用vlc.so库

前言
    我的小程序实现了用VLC的解码库播放远程RTSP流,并实现远程控制
  1. 前期准备
     2.  移植

  • 将vlc-android/libs/下拷贝到你的工程下合并libs目录
  • 需要将下图的vlc-android目录下的源码移植到自己的工程下
   3. 下面是我的参考代码
      layout的xml文件
     
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:paddingBottom="@dimen/activity_vertical_margin"
  6. android:paddingLeft="@dimen/activity_horizontal_margin"
  7. android:paddingRight="@dimen/activity_horizontal_margin"
  8. android:paddingTop="@dimen/activity_vertical_margin"
  9. tools:context="com.example.test.MainActivity" >
  10. <LinearLayout
  11. android:layout_width="match_parent"
  12. android:layout_height="wrap_content"
  13. android:orientation="horizontal" >
  14. <EditText
  15. android:id="@+id/ip"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:layout_marginTop="0dp"
  19. android:layout_weight="20"
  20. android:maxLines="1"
  21. android:singleLine="true" />
  22. <Button
  23. android:id="@+id/con"
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:layout_marginTop="0dp"
  27. android:layout_toRightOf="@+id/ip"
  28. android:layout_weight="1"
  29. android:text= "连接" />
  30. </LinearLayout>
  31. <SurfaceView
  32. android:id="@+id/surfaceView1"
  33. android:layout_width="fill_parent"
  34. android:layout_height="fill_parent"
  35. android:layout_alignParentLeft="true"
  36. android:layout_alignParentTop="true"
  37. android:layout_marginTop="50dp" />
  38. </RelativeLayout>

主要要代码
    
  1. package com.example.test;
  2. import java.io.IOException;
  3. import java.io.OutputStream;
  4. import java.io.UnsupportedEncodingException;
  5. import java.net.Socket;
  6. import java.net.UnknownHostException;
  7. import org.videolan.libvlc.EventHandler;
  8. import org.videolan.libvlc.IVideoPlayer;
  9. import org.videolan.libvlc.LibVLC;
  10. import org.videolan.libvlc.LibVlcException;
  11. import org.videolan.libvlc.LibVlcUtil;
  12. import org.videolan.libvlc.Media;
  13. import org.videolan.vlc.util.VLCInstance;
  14. import org.videolan.vlc.util.WeakHandler;
  15. import android.app.Activity;
  16. import android.content.Context;
  17. import android.content.SharedPreferences;
  18. import android.content.res.Configuration;
  19. import android.graphics.ImageFormat;
  20. import android.graphics.PixelFormat;
  21. import android.media.AudioManager;
  22. import android.media.MediaPlayer;
  23. import android.os.Bundle;
  24. import android.os.Handler;
  25. import android.os.Message;
  26. import android.preference.PreferenceManager;
  27. import android.util.DisplayMetrics;
  28. import android.util.Log;
  29. import android.view.KeyEvent;
  30. import android.view.Menu;
  31. import android.view.MenuItem;
  32. import android.view.MotionEvent;
  33. import android.view.SurfaceHolder;
  34. import android.view.SurfaceHolder.Callback;
  35. import android.view.SurfaceView;
  36. import android.view.View;
  37. import android.view.ViewGroup.LayoutParams;
  38. import android.view.inputmethod.EditorInfo;
  39. import android.view.inputmethod.InputMethodManager;
  40. import android.widget.Button;
  41. import android.widget.EditText;
  42. import android.widget.TextView;
  43. public class MainActivity extends Activity implements IVideoPlayer{
  44. String TAG = "Lee";
  45. private SurfaceView surfaceView;
  46. private SurfaceHolder surfaceHolder;
  47. private String mLocation;
  48. private LibVLC mLibVLC;
  49. private int savedIndexPosition = -1;
  50. private int mLastAudioTrack = -1;
  51. private int mLastSpuTrack = -2;
  52. private AudioManager mAudioManager;
  53. private int mAudioMax;
  54. private SharedPreferences mSettings;
  55. private static final int SURFACE_BEST_FIT = 0;
  56. private static final int SURFACE_FIT_HORIZONTAL = 1;
  57. private static final int SURFACE_FIT_VERTICAL = 2;
  58. private static final int SURFACE_FILL = 3;
  59. private static final int SURFACE_16_9 = 4;
  60. private static final int SURFACE_4_3 = 5;
  61. private static final int SURFACE_ORIGINAL = 6;
  62. private int mCurrentSize = SURFACE_BEST_FIT;
  63. private boolean mIsPlaying;
  64. private int mVideoHeight;
  65. <span style="white-space:pre"> </span>private int mVideoWidth;
  66. <span style="white-space:pre"> </span>private int mSarNum;
  67. <span style="white-space:pre"> </span>private int mSarDen;
  68. <span style="white-space:pre"> </span>private int mSurfaceAlign;
  69. <span style="white-space:pre"> </span>private static final int OVERLAY_TIMEOUT = 4000;
  70. <span style="white-space:pre"> </span>private static final int OVERLAY_INFINITE = 3600000;
  71. <span style="white-space:pre"> </span>private static final int FADE_OUT = 1;
  72. <span style="white-space:pre"> </span>private static final int SHOW_PROGRESS = 2;
  73. <span style="white-space:pre"> </span>private static final int SURFACE_SIZE = 3;
  74. <span style="white-space:pre"> </span>private static final int AUDIO_SERVICE_CONNECTION_SUCCESS = 5;
  75. <span style="white-space:pre"> </span>private static final int AUDIO_SERVICE_CONNECTION_FAILED = 6;
  76. <span style="white-space:pre"> </span>private static final int FADE_OUT_INFO = 4;
  77. <span style="white-space:pre"> </span>private EventHandler eventandler;
  78. /*socket 连接控制部分*/
  79. private Socket clientSocket = null;
  80. private OutputStream outStream = null;
  81. <span style="white-space:pre"> </span>int x = 0;
  82. <span style="white-space:pre"> </span>int y = 0;
  83. <span style="white-space:pre"> </span>int action = -1;
  84. <span style="white-space:pre"> </span>int hostw = 0;
  85. <span style="white-space:pre"> </span>int hosth = 0;
  86. <span style="white-space:pre"> </span>int surfx = 0;
  87. <span style="white-space:pre"> </span>int surfy = 0;
  88. <span style="white-space:pre"> </span>byte[] msgBuffer = null;
  89. <span style="white-space:pre"> </span>String out = null;
  90. boolean change = false;
  91. boolean connected = false;
  92. DisplayMetrics dm = null;
  93. public static Context instance;
  94. private SendThread mSendThread = null;
  95. <span style="white-space:pre"> </span>private String ip_adress;
  96. private EditText ip;
  97. <span style="white-space:pre"> </span>private Button con;
  98. @Override
  99. public boolean dispatchTouchEvent(MotionEvent ev) {
  100. // TODO Auto-generated method stub
  101. x = (int) ev.getX() - surfx;
  102. y = (int) ev.getY() - surfy;
  103. action = ev.getAction();
  104. if ( x < 0 || y < 0 || x > hostw || y > hosth) {
  105. change = false;
  106. } else
  107. change = true;
  108. String out = Integer.toString(hostw) + ";"
  109. + Integer.toString(hosth) + ";"
  110. + Integer.toString(action) + ";"
  111. + Integer.toString(x) + ";"
  112. + Integer.toString(y) ;
  113. try {
  114. msgBuffer = out.getBytes("utf-8");
  115. if(change && connected){
  116. outStream = clientSocket.getOutputStream();
  117. outStream.write(msgBuffer);
  118. Log.e("Send", "Send msg:" + out);;
  119. }
  120. } catch (UnsupportedEncodingException e) {
  121. // TODO Auto-generated catch block
  122. e.printStackTrace();
  123. } catch (IOException e) {
  124. // TODO Auto-generated catch block
  125. e.printStackTrace();
  126. }
  127. return super.dispatchTouchEvent(ev);
  128. }
  129. @Override
  130. protected void onCreate(Bundle savedInstanceState) {
  131. super.onCreate(savedInstanceState);
  132. setContentView(R.layout.activity_main);
  133. instance = this;
  134. final InputMethodManager inputmanger = (InputMethodManager) getSystemService(instance.INPUT_METHOD_SERVICE);
  135. ip = (EditText) findViewById(R.id.ip);
  136. con = (Button) findViewById(R.id.con);
  137. dm = new DisplayMetrics();
  138. surfaceView = (SurfaceView) findViewById(R.id.surfaceView1);
  139. surfaceHolder = surfaceView.getHolder();
  140. surfaceHolder.addCallback(mSurfaceCallback);
  141. surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
  142. surfaceView.setKeepScreenOn(true);
  143. SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
  144. int pitch;
  145. String chroma = pref.getString("chroma_format", "");
  146. if(LibVlcUtil.isGingerbreadOrLater() && chroma.equals("YV12")) {
  147. surfaceHolder.setFormat(ImageFormat.YV12);
  148. pitch = ImageFormat.getBitsPerPixel(ImageFormat.YV12) / 8;
  149. } else if (chroma.equals("RV16")) {
  150. surfaceHolder.setFormat(PixelFormat.RGB_565);
  151. PixelFormat info = new PixelFormat();
  152. PixelFormat.getPixelFormatInfo(PixelFormat.RGB_565, info);
  153. pitch = info.bytesPerPixel;
  154. } else {
  155. surfaceHolder.setFormat(PixelFormat.RGBX_8888);
  156. PixelFormat info = new PixelFormat();
  157. PixelFormat.getPixelFormatInfo(PixelFormat.RGBX_8888, info);
  158. pitch = info.bytesPerPixel;
  159. }
  160. mSurfaceAlign = 16 / pitch - 1;
  161. try {
  162. mLibVLC = VLCInstance.getLibVlcInstance();
  163. } catch (LibVlcException e) {
  164. Log.i(TAG, "LibVLC.getInstance() error:"+e.toString());
  165. e.printStackTrace();
  166. return ;
  167. }
  168. mLibVLC.eventVideoPlayerActivityCreated(true);
  169. eventandler = EventHandler.getInstance();
  170. eventandler.addHandler(mEventHandler);
  171. con.setOnClickListener(new Button.OnClickListener(){
  172. @Override
  173. public void onClick(View v) {
  174. // TODO Auto-generated method stub
  175. ip_adress = ip.getText().toString();
  176. <span style="white-space:pre"> </span>mSendThread = new SendThread();
  177. <span style="white-space:pre"> </span>mSendThread.start();
  178. inputmanger.hideSoftInputFromWindow(ip.getWindowToken(), 0);
  179. }
  180. });
  181. ip.setOnEditorActionListener(new EditText.OnEditorActionListener() {
  182. @Override
  183. public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
  184. // TODO Auto-generated method stub
  185. if (actionId == EditorInfo.IME_ACTION_DONE) {
  186. inputmanger.hideSoftInputFromWindow(ip.getWindowToken(), 0);
  187. ip_adress = ip.getText().toString();
  188. mLocation = "rtsp://" + ip_adress + ":8554/h263ESVideoTest";
  189. mSendThread = new SendThread();
  190. mSendThread.start();
  191. return true;
  192. }
  193. return false;
  194. }
  195. });
  196. }
  197. @Override
  198. public boolean onCreateOptionsMenu(Menu menu) {
  199. // Inflate the menu; this adds items to the action bar if it is present.
  200. getMenuInflater().inflate(R.menu.main, menu);
  201. return true;
  202. }
  203. @Override
  204. public boolean onOptionsItemSelected(MenuItem item) {
  205. // Handle action bar item clicks here. The action bar will
  206. // automatically handle clicks on the Home/Up button, so long
  207. // as you specify a parent activity in AndroidManifest.xml.
  208. int id = item.getItemId();
  209. if (id == R.id.action_settings) {
  210. return true;
  211. }
  212. return super.onOptionsItemSelected(item);
  213. }
  214. public class SendThread extends Thread
  215. {
  216. @Override
  217. public void run() {
  218. try {
  219. clientSocket = new Socket(ip_adress,8888);
  220. Log.e(TAG, "连接成功");
  221. connected = true;
  222. con.setClickable(false);
  223. } catch (UnknownHostException e) {
  224. // TODO Auto-generated catch block
  225. connected = false;
  226. e.printStackTrace();
  227. } catch (IOException e) {
  228. // TODO Auto-generated catch block
  229. connected = false;
  230. e.printStackTrace();
  231. }
  232. String path = "rtsp://172.16.32.14:8554/h263ESVideoTest";
  233. String rtspurl = "rtsp://" + ip_adress + ":8554/h263ESVideoTest";
  234. // pathUri = LibVLC.getInstance().nativeToURI(path);
  235. // mLocation = LibVLC.PathToURI("/sdcard/boot.mp4");
  236. // Log.e(TAG, "start rtsp");
  237. if (connected) {
  238. mLibVLC.setMediaList();
  239. mLibVLC.getMediaList().add(new Media(mLibVLC, rtspurl));
  240. savedIndexPosition = mLibVLC.getMediaList().size() - 1;
  241. mLibVLC.playIndex(savedIndexPosition);
  242. }
  243. };
  244. }
  245. private final VideoEventHandler mEventHandler = new VideoEventHandler(this);
  246. private final Handler mHandler = new VideoPlayerHandler(this);
  247. private static class VideoPlayerHandler extends WeakHandler<MainActivity> {
  248. public VideoPlayerHandler(MainActivity owner) {
  249. super(owner);
  250. }
  251. @Override
  252. public void handleMessage(Message msg) {
  253. MainActivity activity = getOwner();
  254. if(activity == null) // WeakReference could be GC'ed early
  255. return;
  256. switch (msg.what) {
  257. case SURFACE_SIZE:
  258. activity.changeSurfaceSize();
  259. break;
  260. }
  261. }
  262. };
  263. @Override
  264. public void setSurfaceSize(int width, int height, int visible_width,
  265. int visible_height, int sar_num, int sar_den) {
  266. // TODO Auto-generated method stub
  267. if (width * height == 0)
  268. return;
  269. // store video size
  270. mVideoHeight = height;
  271. mVideoWidth = width;
  272. mSarNum = sar_num;
  273. mSarDen = sar_den;
  274. Message msg = mHandler.obtainMessage(SURFACE_SIZE);
  275. mHandler.sendMessage(msg);
  276. }
  277. private final SurfaceHolder.Callback mSurfaceCallback = new Callback() {
  278. @Override
  279. public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
  280. if(format == PixelFormat.RGBX_8888)
  281. Log.d(TAG, "Pixel format is RGBX_8888");
  282. else if(format == PixelFormat.RGB_565)
  283. Log.d(TAG, "Pixel format is RGB_565");
  284. else if(format == ImageFormat.YV12)
  285. Log.d(TAG, "Pixel format is YV12");
  286. else
  287. Log.d(TAG, "Pixel format is other/unknown");
  288. if(mLibVLC != null){
  289. mLibVLC.attachSurface(surfaceHolder.getSurface(), MainActivity.this);
  290. }
  291. Log.e(TAG, "Surface changed");
  292. int xy[] = new int[2] ;
  293. surfaceView.getLocationOnScreen(xy);
  294. Log.e(TAG, "x: " + xy[0] + ", Y: " + xy[1]);
  295. surfx = xy[0];
  296. surfy = xy[1];
  297. hosth = surfaceView.getHeight();
  298. hostw = surfaceView.getWidth();
  299. }
  300. @Override
  301. public void surfaceCreated(SurfaceHolder holder) {
  302. }
  303. @Override
  304. public void surfaceDestroyed(SurfaceHolder holder) {
  305. if(mLibVLC != null)
  306. mLibVLC.detachSurface();
  307. }
  308. };
  309. public static Context getMainContex() {
  310. return instance;
  311. }
  312. class VideoEventHandler extends WeakHandler<MainActivity>{
  313. public VideoEventHandler(MainActivity owner) {
  314. super(owner);
  315. }
  316. @Override
  317. public void handleMessage(Message msg) {
  318. MainActivity activity = getOwner();
  319. if(activity == null) return;
  320. switch (msg.getData().getInt("event")) {
  321. case EventHandler.MediaPlayerPlaying:
  322. Log.i(TAG, "MediaPlayerPlaying");
  323. mIsPlaying = true;
  324. break;
  325. case EventHandler.MediaPlayerPaused:
  326. Log.i(TAG, "MediaPlayerPaused");
  327. mIsPlaying = false;
  328. break;
  329. case EventHandler.MediaPlayerStopped:
  330. Log.i(TAG, "MediaPlayerStopped");
  331. mIsPlaying = false;
  332. break;
  333. case EventHandler.MediaPlayerEndReached:
  334. Log.i(TAG, "MediaPlayerEndReached");
  335. break;
  336. case EventHandler.MediaPlayerVout:
  337. break;
  338. default:
  339. Log.e(TAG, String.format("Event not handled (0x%x)", msg.getData().getInt("event")));
  340. break;
  341. }
  342. super.handleMessage(msg);
  343. }
  344. }
  345. private void changeSurfaceSize() {
  346. // get screen size
  347. int dw = surfaceView.getWidth();
  348. int dh = surfaceView.getHeight();
  349. // getWindow().getDecorView() doesn't always take orientation into account, we have to correct the values
  350. boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
  351. if (dw > dh && isPortrait || dw < dh && !isPortrait) {
  352. int d = dw;
  353. dw = dh;
  354. dh = d;
  355. }
  356. // sanity check
  357. if (dw * dh == 0 || mVideoWidth * mVideoHeight == 0) {
  358. Log.e(TAG, "Invalid surface size");
  359. return;
  360. }
  361. // compute the aspect ratio
  362. double ar, vw;
  363. double density = (double)mSarNum / (double)mSarDen;
  364. if (density == 1.0) {
  365. /* No indication about the density, assuming 1:1 */
  366. vw = mVideoWidth;
  367. ar = (double)mVideoWidth / (double)mVideoHeight;
  368. } else {
  369. /* Use the specified aspect ratio */
  370. vw = mVideoWidth * density;
  371. ar = vw / mVideoHeight;
  372. }
  373. // compute the display aspect ratio
  374. double dar = (double) dw / (double) dh;
  375. switch (mCurrentSize) {
  376. case SURFACE_BEST_FIT:
  377. if (dar < ar)
  378. dh = (int) (dw / ar);
  379. else
  380. dw = (int) (dh * ar);
  381. break;
  382. case SURFACE_FIT_HORIZONTAL:
  383. dh = (int) (dw / ar);
  384. break;
  385. case SURFACE_FIT_VERTICAL:
  386. dw = (int) (dh * ar);
  387. break;
  388. case SURFACE_FILL:
  389. break;
  390. case SURFACE_16_9:
  391. ar = 16.0 / 9.0;
  392. if (dar < ar)
  393. dh = (int) (dw / ar);
  394. else
  395. dw = (int) (dh * ar);
  396. break;
  397. case SURFACE_4_3:
  398. ar = 4.0 / 3.0;
  399. if (dar < ar)
  400. dh = (int) (dw / ar);
  401. else
  402. dw = (int) (dh * ar);
  403. break;
  404. case SURFACE_ORIGINAL:
  405. dh = mVideoHeight;
  406. dw = (int) vw;
  407. break;
  408. }
  409. // align width on 16bytes
  410. int alignedWidth = (mVideoWidth + mSurfaceAlign) & ~mSurfaceAlign;
  411. // force surface buffer size
  412. surfaceHolder.setFixedSize(alignedWidth, mVideoHeight);
  413. // set display size
  414. LayoutParams lp = surfaceView.getLayoutParams();
  415. lp.width = dw * alignedWidth / mVideoWidth;
  416. lp.height = dh;
  417. surfaceView.setLayoutParams(lp);
  418. surfaceView.invalidate();
  419. }
  420. }

 备注:
1. mLibVLC = LibVLC.getInstance();    用来获取mLIbVLC的实例,其中会初始化LibVLC,在AndroidManifest.xml中要添加android:name="org.videolan.vlc.VLCApplication"这样程序启动时会调用VLCApplication使其生成实例,不会导致LibVLC.getInstance()出错。

2.

本Demo实际与ARM-V7a编译的

String path = "rtsp://172.16.32.14:8554/h263ESVideoTest"; 是网络串流地址

如果播放本地视频请使用

mLocation = LibVLC.PathToURI("/sdcard/boot.mp4");转义为VLC可识别的Uri


3.具体的源码可参考

 另:本demo还实现了向服务端同步本地的touch事件
        客户端可参考https://github.com/deeplee/VLC-Demo
        服务端可参考:https://github.com/deeplee/SocketServer

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/酷酷是懒虫/article/detail/852599
推荐阅读
相关标签
  

闽ICP备14008679号