saki4510t / UVCCamera

library and sample to access to UVC web camera on non-rooted Android device
3.02k stars 1.21k forks source link

Fast stop and start streaming. #245

Open iskander-saitbatalov opened 7 years ago

iskander-saitbatalov commented 7 years ago

Hi. I'm new to UVCCamera.

I have task to stream my video into Blob Storage. For this I want to split the video into pieces in 5 seconds. I took USBCameraTest4 and modified When we streaming () I call

stopStreaming (); startStreaming ();

to end previous streaming file and strart new streaming file.

But instead of the desired result, I get the corrupted files and the following duplicate errors.

10-11 06:38:48.624 2801-2841/com.:uvcservice W/Adreno-EGLSUB: : dequeue native buffer fail: No such device, buffer=0x0, handle=0x0 10-11 06:38:48.624 2801-2841/com.:uvcservice W/Adreno-ES20: : GL_OUT_OF_MEMORY

Please, prompt in what a problem.

P.S. *** - is company name :) P.P.S. main code in the attachment.

issue.zip

jp1017 commented 7 years ago

Try start new video in another new Thread

iskander-saitbatalov commented 7 years ago

@jp1017 Do you mean the new CameraThread?

jp1017 commented 7 years ago

New thread is ok.

BarryAlertPan commented 6 years ago

I also encountered this problem, how do you solve it?

iskander-saitbatalov commented 6 years ago

Hello, my friend. I solved it by collection in Map structure all MediaSurfaceEncoders and their own Id of renderer surfaces. I mean you have map between: MediaSurfaceEncoders <-> int (encoderSurfaceId). The main problem is that when your MediaMuxerWrapper want to stop recording it can't stop momentally, because not all frames was writed. So you need a time for it. But when you instantly start next recording you overwriting previous SurfaceId. My code:

private Map<MediaSurfaceEncoder, Integer> mVideoEncoders = new HashMap<>();
...
void frameAvailableSoon() throws RemoteException {
     for (MediaSurfaceEncoder encoder : mVideoEncoders.keySet()) {
          encoder.frameAvailableSoon();
      }
  }
...
private final MediaEncoder.MediaEncoderListener mMediaEncoderListener = new MediaEncoder.MediaEncoderListener() {
        @Override
        public void onPrepared(final MediaEncoder encoder) {
            if (DEBUG) Log.d(TAG, "onPrepared:encoder=" + encoder);
            mIsRecording = true;
            if (encoder instanceof MediaSurfaceEncoder)
                try {
                    final Surface encoderSurface = ((MediaSurfaceEncoder) encoder).getInputSurface();
                    int encoderSurfaceId = encoderSurface.hashCode();
                    mVideoEncoders.put((MediaSurfaceEncoder) encoder, encoderSurfaceId);
                    mHandler.getRendererHolder().addSurface(encoderSurfaceId, encoderSurface, true);
                } catch (final Exception e) {
                    Log.e(TAG, "onPrepared:", e);
                }
        }

        @Override
        public void onStopped(final MediaEncoder encoder) {
            if (DEBUG) Log.v(TAG, "onStopped:encoder=" + encoder);
            if (mVideoEncoders.size() > 1) {
                Log.e(TAG, "Counts of encoders more than 1.");
            }
            if (encoder instanceof MediaSurfaceEncoder) {
                int encoderSurfaceId = mVideoEncoders.get(encoder);
                try {
                    mIsRecording = false;
                    if (encoderSurfaceId > 0) {
                        try {
                            RendererHolder rendererHolder = mHandler.getRendererHolder();
                            if (rendererHolder != null) {
                                rendererHolder.removeSurface(encoderSurfaceId);
                            }
                        } catch (final Exception e) {
                            Log.w(TAG, e);
                        }
                    }
                    synchronized (mSync) {
                        if (mUVCCamera != null) {
                            mUVCCamera.stopCapture();
                        }
                    }
                    mVideoEncoders.remove(encoder);
                    final MediaMuxerWrapper mediaMuxerWrapper = encoder.getMediaMuxer();
                    if (mediaMuxerWrapper != null) {
                        mHandler.sendMessageDelayed(mHandler.obtainMessage(CameraServer.MSG_MEDIA_UPDATE, mediaMuxerWrapper), 1000);
                    }
                } catch (final Exception e) {
                    Log.e(TAG, "onPrepared:", e);
                }
            }
        }
    };
iskander-saitbatalov commented 6 years ago

@BarryAlertPan Did you find a solution to issue #322?