当前位置:   article > 正文

android大疆无人机直播推流VLC_videofeeder.videodatalistener

videofeeder.videodatalistener

官方给了直播的方法:startStream,最近公司需求是大疆无人机做直播推流给后台服务器,然后在后台可以看到无人机拍摄的内容,实时监控无人机的状态

因为这个最新的大疆官方给出了方法,所以做起来是非常简单的,我是根据官方的demo修改来的,有疑问的请评论和私信,代码在我的csdn下载,可以找到资源

项目地址:https://github.com/wrs13634194612/cf8833.git

先看效果图:手机上的推流和电脑上的推流显示一致

手机效果图是这样的:下面有一个editText,输入你的推流服务器地址,注意和下面的vlc保持一致

 

写一下整个项目的流程吧

1.连接无人机和遥控器,然后手机连接遥控器,打开app,获取到直播流,然后调用直播方法,在电脑上使用vlc进行接收,有一个推流服务器,手机推流到这个服务器地址,vlc打开这个地址,如果收到推流的话,就可以在电脑上进行显示

2.下载vlc官方地址:https://www.videolan.org/vlc/index.html

3.下载好了以后,点击安装。vlc安装步骤我就不说了,反正就是一直点下一步就行,语言选择中文,到了主界面,

选择 “媒体”  -->  “打开网络串流”  ---> 输入你的服务器地址就可以了

4.开始写代码吧  app下面的builder.gradle

目录结构:

  1. apply plugin: 'com.android.application'
  2. // 源代码我传到我的csdn下载里面了,如果没有请私信,联系方式Q:2494075190
  3. android {
  4. compileSdkVersion 28
  5. defaultConfig {
  6. multiDexEnabled true
  7. ndk {
  8. abiFilters 'armeabi-v7a'
  9. }
  10. }
  11. packagingOptions {
  12. exclude 'META-INF/rxjava.properties'
  13. }
  14. packagingOptions{
  15. doNotStrip "*/*/libdjivideo.so"
  16. doNotStrip "*/*/libSDKRelativeJNI.so"
  17. doNotStrip "*/*/libFlyForbid.so"
  18. doNotStrip "*/*/libduml_vision_bokeh.so"
  19. doNotStrip "*/*/libyuv2.so"
  20. doNotStrip "*/*/libGroudStation.so"
  21. doNotStrip "*/*/libFRCorkscrew.so"
  22. doNotStrip "*/*/libUpgradeVerify.so"
  23. doNotStrip "*/*/libFR.so"
  24. }
  25. }
  26. dependencies {
  27. implementation 'com.android.support:multidex:1.0.2'
  28. implementation 'com.squareup:otto:1.3.8'
  29. implementation('com.dji:dji-sdk:4.9', {
  30. // Uncomment the following line if your app does not need Anti Distortion for
  31. // Mavic 2 Pro and Mavic 2 Zoom. It will greatly reducing the size of the APK:
  32. exclude module: 'library-anti-distortion'
  33. })
  34. compileOnly 'com.dji:dji-sdk-provided:4.9'
  35. }

2.主要的application

  1. package com.example.admin.ztest;
  2. import android.app.Application;
  3. import android.content.Context;
  4. import android.os.Process;
  5. import android.text.TextUtils;
  6. import com.secneo.sdk.Helper;
  7. import java.io.BufferedReader;
  8. import java.io.FileReader;
  9. import java.io.IOException;
  10. public class MApplication extends Application {
  11. private FPVDemoApplication fpvDemoApplication;
  12. @Override
  13. protected void attachBaseContext(Context paramContext) {
  14. super.attachBaseContext(paramContext);
  15. Helper.install(MApplication.this);
  16. if (fpvDemoApplication == null) {
  17. fpvDemoApplication = new FPVDemoApplication();
  18. fpvDemoApplication.setContext(this);
  19. }
  20. }
  21. @Override
  22. public void onCreate() {
  23. super.onCreate();
  24. fpvDemoApplication.onCreate();
  25. }
  26. }

3.主界面:

  1. package com.example.admin.ztest;
  2. import android.app.Activity;
  3. import android.content.Intent;
  4. import android.graphics.SurfaceTexture;
  5. import android.os.Handler;
  6. import android.support.annotation.NonNull;
  7. import android.support.v7.app.AppCompatActivity;
  8. import android.os.Bundle;
  9. import android.util.Log;
  10. import android.view.TextureView;
  11. import android.view.View;
  12. import android.widget.Button;
  13. import android.widget.CompoundButton;
  14. import android.widget.ImageView;
  15. import android.widget.TextView;
  16. import android.widget.Toast;
  17. import android.widget.ToggleButton;
  18. import dji.common.camera.SettingsDefinitions;
  19. import dji.common.camera.SystemState;
  20. import dji.common.error.DJIError;
  21. import dji.common.product.Model;
  22. import dji.common.useraccount.UserAccountState;
  23. import dji.common.util.CommonCallbacks;
  24. import dji.log.IFileFormat;
  25. import dji.sdk.base.BaseProduct;
  26. import dji.sdk.camera.Camera;
  27. import dji.sdk.camera.VideoFeeder;
  28. import dji.sdk.codec.DJICodecManager;
  29. import dji.sdk.useraccount.UserAccountManager;
  30. public class MainActivity extends Activity implements TextureView.SurfaceTextureListener, View.OnClickListener {
  31. private static final String TAG = MainActivity.class.getName();
  32. protected VideoFeeder.VideoDataListener mReceivedVideoDataListener = null;
  33. protected DJICodecManager mCodecManager = null;
  34. protected TextureView mVideoSurface = null;
  35. private Button mCaptureBtn, mShootPhotoModeBtn, mRecordVideoModeBtn, btn_battery;
  36. private ToggleButton mRecordBtn;
  37. private TextView recordingTime;
  38. private Handler handler;
  39. //otto同样需要注册和取消注册、订阅事件
  40. private boolean isConnect;
  41. @Override
  42. protected void onCreate(Bundle savedInstanceState) {
  43. super.onCreate(savedInstanceState);
  44. setContentView(R.layout.activity_main);
  45. handler = new Handler();
  46. initUI();
  47. //用于接收摄像机实时视图的原始H264视频数据的回调
  48. mReceivedVideoDataListener = new VideoFeeder.VideoDataListener() {
  49. @Override
  50. public void onReceive(byte[] videoBuffer, int size) {
  51. if (mCodecManager != null) {
  52. mCodecManager.sendDataToDecoder(videoBuffer, size);
  53. }
  54. }
  55. };
  56. final Camera camera = FPVDemoApplication.getCameraInstance();
  57. if (camera != null) {
  58. camera.setSystemStateCallback(new SystemState.Callback() {
  59. @Override
  60. public void onUpdate(@NonNull SystemState cameraSystemState) {
  61. if (null != cameraSystemState) {
  62. final int recordTime = cameraSystemState.getCurrentVideoRecordingTimeInSeconds();
  63. int minutes = (recordTime % 3600) / 60;
  64. int seconds = recordTime % 60;
  65. final String timeString = String.format("%02d:%02d", minutes, seconds);
  66. final boolean isVideorecording = cameraSystemState.isRecording();
  67. MainActivity.this.runOnUiThread(new Runnable() {
  68. @Override
  69. public void run() {
  70. recordingTime.setText(timeString);
  71. if (isVideorecording) {
  72. recordingTime.setVisibility(View.VISIBLE);
  73. } else {
  74. recordingTime.setVisibility(View.INVISIBLE);
  75. }
  76. }
  77. });
  78. }
  79. }
  80. });
  81. }
  82. }
  83. protected void onProductChange() {
  84. initPreviewer();
  85. loginAccount();
  86. }
  87. private void loginAccount() {
  88. UserAccountManager.getInstance().logIntoDJIUserAccount(this, new CommonCallbacks.CompletionCallbackWith<UserAccountState>() {
  89. @Override
  90. public void onSuccess(UserAccountState userAccountState) {
  91. Log.e(TAG, "Login success");
  92. }
  93. @Override
  94. public void onFailure(DJIError djiError) {
  95. showToast("Login Error" + djiError.getDescription());
  96. }
  97. });
  98. }
  99. @Override
  100. protected void onResume() {
  101. super.onResume();
  102. initPreviewer();
  103. onProductChange();
  104. if (mVideoSurface == null) {
  105. Log.e(TAG, "mVideosurface is nnull");
  106. }
  107. }
  108. @Override
  109. protected void onPause() {
  110. super.onPause();
  111. uninitPreviewer();
  112. }
  113. @Override
  114. protected void onStop() {
  115. super.onStop();
  116. }
  117. public void onReturn(View view) {
  118. this.finish();
  119. }
  120. @Override
  121. protected void onDestroy() {
  122. super.onDestroy();
  123. uninitPreviewer();
  124. }
  125. private void initUI() {
  126. mVideoSurface = (TextureView) findViewById(R.id.video_previewer_surface);
  127. recordingTime = (TextView) findViewById(R.id.timer);
  128. mCaptureBtn = (Button) findViewById(R.id.btn_capture);
  129. btn_battery = (Button) findViewById(R.id.btn_battery);
  130. mRecordBtn = (ToggleButton) findViewById(R.id.btn_record);
  131. mShootPhotoModeBtn = (Button) findViewById(R.id.btn_shoot_photo_mode);
  132. mRecordVideoModeBtn = (Button) findViewById(R.id.btn_record_video_mode);
  133. if (null != mVideoSurface) {
  134. mVideoSurface.setSurfaceTextureListener(this);
  135. }
  136. mCaptureBtn.setOnClickListener(this);
  137. mRecordBtn.setOnClickListener(this);
  138. mShootPhotoModeBtn.setOnClickListener(this);
  139. mRecordVideoModeBtn.setOnClickListener(this);
  140. recordingTime.setVisibility(View.INVISIBLE);
  141. mRecordBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
  142. @Override
  143. public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
  144. if (isChecked) {
  145. startRecord();
  146. } else {
  147. stopRecord();
  148. }
  149. }
  150. });
  151. btn_battery.setOnClickListener(new View.OnClickListener() {
  152. @Override
  153. public void onClick(View v) {
  154. //Intent intent = new Intent(MainActivity.this, BattryActivity.class);
  155. // startActivity(intent);
  156. }
  157. });
  158. }
  159. private void initPreviewer() {
  160. BaseProduct product = FPVDemoApplication.getProductInstance();
  161. if (product == null || !product.isConnected()) {
  162. showToast(getString(R.string.disconnected));
  163. } else {
  164. if (null != mVideoSurface) {
  165. mVideoSurface.setSurfaceTextureListener(this);
  166. }
  167. if (!product.getModel().equals(Model.UNKNOWN_AIRCRAFT)) {
  168. VideoFeeder.getInstance().getPrimaryVideoFeed().addVideoDataListener(mReceivedVideoDataListener);
  169. }
  170. }
  171. }
  172. private void uninitPreviewer() {
  173. Camera camera = FPVDemoApplication.getCameraInstance();
  174. if (camera != null) {
  175. VideoFeeder.getInstance().getPrimaryVideoFeed().addVideoDataListener(null);
  176. }
  177. }
  178. public void showToast(final String msg) {
  179. runOnUiThread(new Runnable() {
  180. @Override
  181. public void run() {
  182. Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
  183. }
  184. });
  185. }
  186. @Override
  187. public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
  188. if (mCodecManager == null) {
  189. mCodecManager = new DJICodecManager(this, surface, width, height);
  190. }
  191. }
  192. @Override
  193. public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
  194. }
  195. @Override
  196. public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
  197. if (mCodecManager != null) {
  198. mCodecManager.cleanSurface();
  199. mCodecManager = null;
  200. }
  201. return false;
  202. }
  203. @Override
  204. public void onSurfaceTextureUpdated(SurfaceTexture surface) {
  205. }
  206. @Override
  207. public void onClick(View v) {
  208. switch (v.getId()) {
  209. case R.id.btn_capture: {
  210. captureAction();
  211. break;
  212. }
  213. case R.id.btn_shoot_photo_mode: {
  214. switchCameraMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO);
  215. break;
  216. }
  217. case R.id.btn_record_video_mode: {
  218. switchCameraMode(SettingsDefinitions.CameraMode.RECORD_VIDEO);
  219. break;
  220. }
  221. default:
  222. break;
  223. }
  224. }
  225. private void switchCameraMode(SettingsDefinitions.CameraMode cameraMode) {
  226. Camera camera = FPVDemoApplication.getCameraInstance();
  227. if (camera != null) {
  228. camera.setMode(cameraMode, new CommonCallbacks.CompletionCallback() {
  229. @Override
  230. public void onResult(DJIError djiError) {
  231. if (djiError == null) {
  232. showToast("Switch Camera Mode Succeeded");
  233. } else {
  234. showToast(djiError.getDescription());
  235. }
  236. }
  237. });
  238. }
  239. }
  240. private void captureAction() {
  241. final Camera camera = FPVDemoApplication.getCameraInstance();
  242. if (camera != null) {
  243. SettingsDefinitions.ShootPhotoMode photoMode = SettingsDefinitions.ShootPhotoMode.SINGLE;
  244. camera.setShootPhotoMode(photoMode, new CommonCallbacks.CompletionCallback() {
  245. @Override
  246. public void onResult(DJIError djiError) {
  247. if (null == djiError) {
  248. handler.postDelayed(new Runnable() {
  249. @Override
  250. public void run() {
  251. //延时2s执行
  252. camera.startShootPhoto(new CommonCallbacks.CompletionCallback() {
  253. @Override
  254. public void onResult(DJIError djiError) {
  255. if (djiError == null) {
  256. showToast("take photo :success");
  257. } else {
  258. showToast(djiError.getDescription());
  259. }
  260. }
  261. });
  262. }
  263. }, 2000);
  264. }
  265. }
  266. });
  267. }
  268. }
  269. private void startRecord() {
  270. final Camera camera = FPVDemoApplication.getCameraInstance();
  271. if (camera != null) {
  272. camera.startRecordVideo(new CommonCallbacks.CompletionCallback() {
  273. @Override
  274. public void onResult(DJIError djiError) {
  275. if (djiError == null) {
  276. showToast("Record video success");
  277. } else {
  278. showToast(djiError.getDescription());
  279. }
  280. }
  281. });
  282. }
  283. }
  284. private void stopRecord() {
  285. Camera camera = FPVDemoApplication.getCameraInstance();
  286. if (camera != null) {
  287. camera.stopRecordVideo(new CommonCallbacks.CompletionCallback() {
  288. @Override
  289. public void onResult(DJIError djiError) {
  290. if (djiError == null) {
  291. showToast("Stop recording success");
  292. } else {
  293. showToast(djiError.getDescription());
  294. }
  295. }
  296. });
  297. }
  298. }
  299. }

4.连接无人机:

  1. package com.example.admin.ztest;
  2. import android.app.Application;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.os.Build;
  6. import android.os.Handler;
  7. import android.os.Looper;
  8. import android.support.v4.content.ContextCompat;
  9. import android.util.Log;
  10. import android.widget.Toast;
  11. import dji.common.error.DJIError;
  12. import dji.common.error.DJISDKError;
  13. import dji.sdk.base.BaseComponent;
  14. import dji.sdk.base.BaseProduct;
  15. import dji.sdk.battery.Battery;
  16. import dji.sdk.camera.Camera;
  17. import dji.sdk.products.Aircraft;
  18. import dji.sdk.products.HandHeld;
  19. import dji.sdk.sdkmanager.DJISDKManager;
  20. public class FPVDemoApplication extends Application {
  21. public static final String FLAG_CONNECTION_CHANGE = "fpv_tutorial_connection_change";
  22. private DJISDKManager.SDKManagerCallback mDJISDKManagerCallback;
  23. private static BaseProduct mProduct;
  24. public Handler mHandler;
  25. private Application instance;
  26. public void setContext(Application application) {
  27. instance = application;
  28. }
  29. @Override
  30. public Context getApplicationContext() {
  31. return instance;
  32. }
  33. public FPVDemoApplication() {
  34. }
  35. /**
  36. * This function is used to get the instance of DJIBaseProduct.
  37. * If no product is connected, it returns null.
  38. */
  39. public static synchronized BaseProduct getProductInstance() {
  40. if (null == mProduct) {
  41. mProduct = DJISDKManager.getInstance().getProduct();
  42. }
  43. return mProduct;
  44. }
  45. //电池
  46. public static synchronized Battery getBatter
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号