Set up an external video source
Note
This example is a part of the Vision SDK Examples. You can find the values for all referenced resources in the res
directory. For example, see res/values/strings.xml
for R.string.*
references used in this example.
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"> <com.mapbox.vision.view.VisionViewandroid:id="@+id/vision_view"android:layout_width="match_parent"android:layout_height="match_parent"app:visualization_mode="clear" /> <FrameLayoutandroid:id="@+id/speed_alert_view"android:layout_width="@dimen/speed_limit_view_width"android:layout_height="@dimen/speed_limit_view_height"android:layout_gravity="end|top"android:layout_margin="15dp"android:visibility="gone"> <ImageViewandroid:id="@+id/speed_sign_view"android:layout_width="@dimen/speed_limit_view_width"android:layout_height="@dimen/speed_limit_view_height"android:src="@drawable/speed_limit_normal" /> <TextViewandroid:id="@+id/speed_value_view"android:layout_width="@dimen/speed_limit_speed_view_width"android:layout_height="@dimen/speed_limit_speed_view_height"android:layout_gravity="bottom|center_horizontal"android:layout_marginBottom="10dp"android:gravity="center"android:textSize="40dp"android:textStyle="bold"tools:ignore="SpUsage"tools:text="40" /></FrameLayout> </FrameLayout>
package com.mapbox.vision.examples; import android.graphics.Bitmap;import android.media.MediaMetadataRetriever;import android.os.Handler;import android.os.HandlerThread; import com.mapbox.vision.VisionManager;import com.mapbox.vision.mobile.core.interfaces.VisionEventsListener;import com.mapbox.vision.mobile.core.models.AuthorizationStatus;import com.mapbox.vision.mobile.core.models.Camera;import com.mapbox.vision.mobile.core.models.Country;import com.mapbox.vision.mobile.core.models.FrameSegmentation;import com.mapbox.vision.mobile.core.models.classification.FrameSignClassifications;import com.mapbox.vision.mobile.core.models.detection.FrameDetections;import com.mapbox.vision.mobile.core.models.frame.ImageFormat;import com.mapbox.vision.mobile.core.models.frame.ImageSize;import com.mapbox.vision.mobile.core.models.position.VehicleState;import com.mapbox.vision.mobile.core.models.road.RoadDescription;import com.mapbox.vision.mobile.core.models.world.WorldDescription;import com.mapbox.vision.video.videosource.VideoSource;import com.mapbox.vision.video.videosource.VideoSourceListener;import com.mapbox.vision.view.VisionView; import org.jetbrains.annotations.NotNull; import java.nio.ByteBuffer;import java.util.concurrent.TimeUnit; /*** Example shows how Vision SDK can work with external video source. This can be some custom camera implementation or any* other source of frames - video, set of pictures, etc.*/public class ExternalVideoSourceActivity extends BaseActivity { // Video file that will be processed.private static final String PATH_TO_VIDEO_FILE = "path_to_video_file"; private VideoSourceListener videoSourceListener;private VisionView visionView;private HandlerThread handlerThread = new HandlerThread("VideoDecode");private boolean visionManagerWasInit = false; // VideoSource that will play the file.private VideoSource customVideoSource = new VideoSource() {@Overridepublic void attach(@NotNull VideoSourceListener videoSourceListener) {// video source is attached, we can start decoding frames from video and feeding them to Vision SDK.ExternalVideoSourceActivity.this.videoSourceListener = videoSourceListener;handlerThread.start();new Handler(handlerThread.getLooper()).post(() -> startFileVideoSource());} @Overridepublic void detach() {videoSourceListener = null;handlerThread.quitSafely();}}; // VisionEventsListener handles events from Vision SDK on background thread.private VisionEventsListener visionEventsListener = new VisionEventsListener() { @Overridepublic void onAuthorizationStatusUpdated(@NotNull AuthorizationStatus authorizationStatus) {} @Overridepublic void onFrameSegmentationUpdated(@NotNull FrameSegmentation frameSegmentation) {} @Overridepublic void onFrameDetectionsUpdated(@NotNull FrameDetections frameDetections) { } @Overridepublic void onFrameSignClassificationsUpdated(@NotNull FrameSignClassifications frameSignClassifications) {} @Overridepublic void onRoadDescriptionUpdated(@NotNull RoadDescription roadDescription) {} @Overridepublic void onWorldDescriptionUpdated(@NotNull WorldDescription worldDescription) {} @Overridepublic void onVehicleStateUpdated(@NotNull VehicleState vehicleState) {} @Overridepublic void onCameraUpdated(@NotNull Camera camera) {} @Overridepublic void onCountryUpdated(@NotNull Country country) {} @Overridepublic void onUpdateCompleted() {}}; @Overrideprotected void initViews() {setContentView(R.layout.activity_main);visionView = findViewById(R.id.vision_view);} @Overrideprotected void onPermissionsGranted() {startVisionManager();} @Overrideprotected void onStart() {super.onStart();startVisionManager();} @Overrideprotected void onStop() {super.onStop();stopVisionManager();} @Overrideprotected void onResume() {super.onResume();visionView.onResume();} @Overrideprotected void onPause() {super.onPause();visionView.onPause();} private void startVisionManager() {if (allPermissionsGranted() && !visionManagerWasInit) {VisionManager.create(customVideoSource);visionView.setVisionManager(VisionManager.INSTANCE);VisionManager.setVisionEventsListener(visionEventsListener);VisionManager.start(); visionManagerWasInit = true;}} private void stopVisionManager() {if (visionManagerWasInit) {VisionManager.stop();VisionManager.destroy(); visionManagerWasInit = false;}} /*** Decodes video source frame by frame and feeds frames to Vision SDK.*/private void startFileVideoSource() {// Use MediaMetadataRetriever to decode video.// It isn't the fastest approach to decode videos and you probably want some other method.// if FPS is important (eg. MediaCodec).MediaMetadataRetriever retriever = new MediaMetadataRetriever();retriever.setDataSource(PATH_TO_VIDEO_FILE); // Get video frame size.int frameWidth = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));int frameHeight = Integer.parseInt(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));ImageSize imageSize = new ImageSize(frameWidth, frameHeight);// ByteBuffer to hold RGBA bytes.ByteBuffer rgbaByteBuffer = ByteBuffer.allocateDirect(frameWidth * frameHeight * 4); // Get duration.long duration = Long.parseLong(retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)); try {// Get frames one by one with 1 second intervals.for (int seconds = 0; seconds < duration; seconds++) {Bitmap bitmap = retriever.getFrameAtTime(TimeUnit.SECONDS.toMicros(seconds),MediaMetadataRetriever.OPTION_CLOSEST).copy(Bitmap.Config.ARGB_8888, false); bitmap.copyPixelsToBuffer(rgbaByteBuffer); videoSourceListener.onNewFrame(new VideoSourceListener.FrameHolder.ByteBufferHolder(rgbaByteBuffer),ImageFormat.RGBA,imageSize);rgbaByteBuffer.clear();}} catch (RuntimeException e) {e.printStackTrace();} finally {try {retriever.release();} catch (RuntimeException e) {e.printStackTrace();}}}}