<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.test.MainActivity" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <EditText android:id="@+id/ip" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="0dp" android:layout_weight="20" android:maxLines="1" android:singleLine="true" /> <Button android:id="@+id/con" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="0dp" android:layout_toRightOf="@+id/ip" android:layout_weight="1" android:text= "连接" /> </LinearLayout> <SurfaceView android:id="@+id/surfaceView1" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginTop="50dp" /> </RelativeLayout>
package com.example.test; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.net.UnknownHostException; import org.videolan.libvlc.EventHandler; import org.videolan.libvlc.IVideoPlayer; import org.videolan.libvlc.LibVLC; import org.videolan.libvlc.LibVlcException; import org.videolan.libvlc.LibVlcUtil; import org.videolan.libvlc.Media; import org.videolan.vlc.util.VLCInstance; import org.videolan.vlc.util.WeakHandler; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; import android.graphics.ImageFormat; import android.graphics.PixelFormat; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.preference.PreferenceManager; import android.util.DisplayMetrics; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup.LayoutParams; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class MainActivity extends Activity implements IVideoPlayer{ String TAG = "Lee"; private SurfaceView surfaceView; private SurfaceHolder surfaceHolder; private String mLocation; private LibVLC mLibVLC; private int savedIndexPosition = -1; private int mLastAudioTrack = -1; private int mLastSpuTrack = -2; private AudioManager mAudioManager; private int mAudioMax; private SharedPreferences mSettings; private static final int SURFACE_BEST_FIT = 0; private static final int SURFACE_FIT_HORIZONTAL = 1; private static final int SURFACE_FIT_VERTICAL = 2; private static final int SURFACE_FILL = 3; private static final int SURFACE_16_9 = 4; private static final int SURFACE_4_3 = 5; private static final int SURFACE_ORIGINAL = 6; private int mCurrentSize = SURFACE_BEST_FIT; private boolean mIsPlaying; private int mVideoHeight; <span style="white-space:pre"> </span>private int mVideoWidth; <span style="white-space:pre"> </span>private int mSarNum; <span style="white-space:pre"> </span>private int mSarDen; <span style="white-space:pre"> </span>private int mSurfaceAlign; <span style="white-space:pre"> </span>private static final int OVERLAY_TIMEOUT = 4000; <span style="white-space:pre"> </span>private static final int OVERLAY_INFINITE = 3600000; <span style="white-space:pre"> </span>private static final int FADE_OUT = 1; <span style="white-space:pre"> </span>private static final int SHOW_PROGRESS = 2; <span style="white-space:pre"> </span>private static final int SURFACE_SIZE = 3; <span style="white-space:pre"> </span>private static final int AUDIO_SERVICE_CONNECTION_SUCCESS = 5; <span style="white-space:pre"> </span>private static final int AUDIO_SERVICE_CONNECTION_FAILED = 6; <span style="white-space:pre"> </span>private static final int FADE_OUT_INFO = 4; <span style="white-space:pre"> </span>private EventHandler eventandler; /*socket 连接控制部分*/ private Socket clientSocket = null; private OutputStream outStream = null; <span style="white-space:pre"> </span>int x = 0; <span style="white-space:pre"> </span>int y = 0; <span style="white-space:pre"> </span>int action = -1; <span style="white-space:pre"> </span>int hostw = 0; <span style="white-space:pre"> </span>int hosth = 0; <span style="white-space:pre"> </span>int surfx = 0; <span style="white-space:pre"> </span>int surfy = 0; <span style="white-space:pre"> </span>byte[] msgBuffer = null; <span style="white-space:pre"> </span>String out = null; boolean change = false; boolean connected = false; DisplayMetrics dm = null; public static Context instance; private SendThread mSendThread = null; <span style="white-space:pre"> </span>private String ip_adress; private EditText ip; <span style="white-space:pre"> </span>private Button con; @Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub x = (int) ev.getX() - surfx; y = (int) ev.getY() - surfy; action = ev.getAction(); if ( x < 0 || y < 0 || x > hostw || y > hosth) { change = false; } else change = true; String out = Integer.toString(hostw) + ";" + Integer.toString(hosth) + ";" + Integer.toString(action) + ";" + Integer.toString(x) + ";" + Integer.toString(y) ; try { msgBuffer = out.getBytes("utf-8"); if(change && connected){ outStream = clientSocket.getOutputStream(); outStream.write(msgBuffer); Log.e("Send", "Send msg:" + out);; } } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return super.dispatchTouchEvent(ev); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); instance = this; final InputMethodManager inputmanger = (InputMethodManager) getSystemService(instance.INPUT_METHOD_SERVICE); ip = (EditText) findViewById(R.id.ip); con = (Button) findViewById(R.id.con); dm = new DisplayMetrics(); surfaceView = (SurfaceView) findViewById(R.id.surfaceView1); surfaceHolder = surfaceView.getHolder(); surfaceHolder.addCallback(mSurfaceCallback); surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.setKeepScreenOn(true); SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this); int pitch; String chroma = pref.getString("chroma_format", ""); if(LibVlcUtil.isGingerbreadOrLater() && chroma.equals("YV12")) { surfaceHolder.setFormat(ImageFormat.YV12); pitch = ImageFormat.getBitsPerPixel(ImageFormat.YV12) / 8; } else if (chroma.equals("RV16")) { surfaceHolder.setFormat(PixelFormat.RGB_565); PixelFormat info = new PixelFormat(); PixelFormat.getPixelFormatInfo(PixelFormat.RGB_565, info); pitch = info.bytesPerPixel; } else { surfaceHolder.setFormat(PixelFormat.RGBX_8888); PixelFormat info = new PixelFormat(); PixelFormat.getPixelFormatInfo(PixelFormat.RGBX_8888, info); pitch = info.bytesPerPixel; } mSurfaceAlign = 16 / pitch - 1; try { mLibVLC = VLCInstance.getLibVlcInstance(); } catch (LibVlcException e) { Log.i(TAG, "LibVLC.getInstance() error:"+e.toString()); e.printStackTrace(); return ; } mLibVLC.eventVideoPlayerActivityCreated(true); eventandler = EventHandler.getInstance(); eventandler.addHandler(mEventHandler); con.setOnClickListener(new Button.OnClickListener(){ @Override public void onClick(View v) { // TODO Auto-generated method stub ip_adress = ip.getText().toString(); <span style="white-space:pre"> </span>mSendThread = new SendThread(); <span style="white-space:pre"> </span>mSendThread.start(); inputmanger.hideSoftInputFromWindow(ip.getWindowToken(), 0); } }); ip.setOnEditorActionListener(new EditText.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { // TODO Auto-generated method stub if (actionId == EditorInfo.IME_ACTION_DONE) { inputmanger.hideSoftInputFromWindow(ip.getWindowToken(), 0); ip_adress = ip.getText().toString(); mLocation = "rtsp://" + ip_adress + ":8554/h263ESVideoTest"; mSendThread = new SendThread(); mSendThread.start(); return true; } return false; } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } public class SendThread extends Thread { @Override public void run() { try { clientSocket = new Socket(ip_adress,8888); Log.e(TAG, "连接成功"); connected = true; con.setClickable(false); } catch (UnknownHostException e) { // TODO Auto-generated catch block connected = false; e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block connected = false; e.printStackTrace(); } String path = "rtsp://172.16.32.14:8554/h263ESVideoTest"; String rtspurl = "rtsp://" + ip_adress + ":8554/h263ESVideoTest"; // pathUri = LibVLC.getInstance().nativeToURI(path); // mLocation = LibVLC.PathToURI("/sdcard/boot.mp4"); // Log.e(TAG, "start rtsp"); if (connected) { mLibVLC.setMediaList(); mLibVLC.getMediaList().add(new Media(mLibVLC, rtspurl)); savedIndexPosition = mLibVLC.getMediaList().size() - 1; mLibVLC.playIndex(savedIndexPosition); } }; } private final VideoEventHandler mEventHandler = new VideoEventHandler(this); private final Handler mHandler = new VideoPlayerHandler(this); private static class VideoPlayerHandler extends WeakHandler<MainActivity> { public VideoPlayerHandler(MainActivity owner) { super(owner); } @Override public void handleMessage(Message msg) { MainActivity activity = getOwner(); if(activity == null) // WeakReference could be GC'ed early return; switch (msg.what) { case SURFACE_SIZE: activity.changeSurfaceSize(); break; } } }; @Override public void setSurfaceSize(int width, int height, int visible_width, int visible_height, int sar_num, int sar_den) { // TODO Auto-generated method stub if (width * height == 0) return; // store video size mVideoHeight = height; mVideoWidth = width; mSarNum = sar_num; mSarDen = sar_den; Message msg = mHandler.obtainMessage(SURFACE_SIZE); mHandler.sendMessage(msg); } private final SurfaceHolder.Callback mSurfaceCallback = new Callback() { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if(format == PixelFormat.RGBX_8888) Log.d(TAG, "Pixel format is RGBX_8888"); else if(format == PixelFormat.RGB_565) Log.d(TAG, "Pixel format is RGB_565"); else if(format == ImageFormat.YV12) Log.d(TAG, "Pixel format is YV12"); else Log.d(TAG, "Pixel format is other/unknown"); if(mLibVLC != null){ mLibVLC.attachSurface(surfaceHolder.getSurface(), MainActivity.this); } Log.e(TAG, "Surface changed"); int xy[] = new int[2] ; surfaceView.getLocationOnScreen(xy); Log.e(TAG, "x: " + xy[0] + ", Y: " + xy[1]); surfx = xy[0]; surfy = xy[1]; hosth = surfaceView.getHeight(); hostw = surfaceView.getWidth(); } @Override public void surfaceCreated(SurfaceHolder holder) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { if(mLibVLC != null) mLibVLC.detachSurface(); } }; public static Context getMainContex() { return instance; } class VideoEventHandler extends WeakHandler<MainActivity>{ public VideoEventHandler(MainActivity owner) { super(owner); } @Override public void handleMessage(Message msg) { MainActivity activity = getOwner(); if(activity == null) return; switch (msg.getData().getInt("event")) { case EventHandler.MediaPlayerPlaying: Log.i(TAG, "MediaPlayerPlaying"); mIsPlaying = true; break; case EventHandler.MediaPlayerPaused: Log.i(TAG, "MediaPlayerPaused"); mIsPlaying = false; break; case EventHandler.MediaPlayerStopped: Log.i(TAG, "MediaPlayerStopped"); mIsPlaying = false; break; case EventHandler.MediaPlayerEndReached: Log.i(TAG, "MediaPlayerEndReached"); break; case EventHandler.MediaPlayerVout: break; default: Log.e(TAG, String.format("Event not handled (0x%x)", msg.getData().getInt("event"))); break; } super.handleMessage(msg); } } private void changeSurfaceSize() { // get screen size int dw = surfaceView.getWidth(); int dh = surfaceView.getHeight(); // getWindow().getDecorView() doesn't always take orientation into account, we have to correct the values boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT; if (dw > dh && isPortrait || dw < dh && !isPortrait) { int d = dw; dw = dh; dh = d; } // sanity check if (dw * dh == 0 || mVideoWidth * mVideoHeight == 0) { Log.e(TAG, "Invalid surface size"); return; } // compute the aspect ratio double ar, vw; double density = (double)mSarNum / (double)mSarDen; if (density == 1.0) { /* No indication about the density, assuming 1:1 */ vw = mVideoWidth; ar = (double)mVideoWidth / (double)mVideoHeight; } else { /* Use the specified aspect ratio */ vw = mVideoWidth * density; ar = vw / mVideoHeight; } // compute the display aspect ratio double dar = (double) dw / (double) dh; switch (mCurrentSize) { case SURFACE_BEST_FIT: if (dar < ar) dh = (int) (dw / ar); else dw = (int) (dh * ar); break; case SURFACE_FIT_HORIZONTAL: dh = (int) (dw / ar); break; case SURFACE_FIT_VERTICAL: dw = (int) (dh * ar); break; case SURFACE_FILL: break; case SURFACE_16_9: ar = 16.0 / 9.0; if (dar < ar) dh = (int) (dw / ar); else dw = (int) (dh * ar); break; case SURFACE_4_3: ar = 4.0 / 3.0; if (dar < ar) dh = (int) (dw / ar); else dw = (int) (dh * ar); break; case SURFACE_ORIGINAL: dh = mVideoHeight; dw = (int) vw; break; } // align width on 16bytes int alignedWidth = (mVideoWidth + mSurfaceAlign) & ~mSurfaceAlign; // force surface buffer size surfaceHolder.setFixedSize(alignedWidth, mVideoHeight); // set display size LayoutParams lp = surfaceView.getLayoutParams(); lp.width = dw * alignedWidth / mVideoWidth; lp.height = dh; surfaceView.setLayoutParams(lp); surfaceView.invalidate(); } }
本Demo实际与ARM-V7a编译的
String path = "rtsp://172.16.32.14:8554/h263ESVideoTest"; 是网络串流地址
如果播放本地视频请使用
mLocation = LibVLC.PathToURI("/sdcard/boot.mp4");转义为VLC可识别的Uri