0
votes

I am working on an App which requires Audio / Video Chat... My problem is when I start capturing video the Audio Playing stops completely.

Technical Description I have used AudioTrack Class and AudioTrack.OnPlaybackPositionUpdateListener for audio playing. I have used Camera and Camera.PreviewCallBack for video Recording.

Now as soon as camera is started, the call back of AudioTrack class stops working. What can I do to handle this problem ? I have HTC's device which has Android2.2.

EDIT Since I can't post full code here... (I don't have access to the code of Video module), I am listing the scenario here:-

  1. Audio chat has been started and Audio is playing, which means onPeriodicNotification() is called properly..

public void start() {

    bufferSize = AudioTrack.getMinBufferSize(sampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);

    if (bufferSize != AudioTrack.ERROR_BAD_VALUE && bufferSize != AudioTrack.ERROR) {
        audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, this.sampleRateInHz, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT,
                this.bufferSize, AudioTrack.MODE_STREAM);
        if (audioTrack != null && audioTrack.getState() == AudioTrack.STATE_INITIALIZED) {
            Log.i(LOG_TAG, "Audio Track instance created buffer Size : " + this.bufferSize);

            audioTrack.setPositionNotificationPeriod(320);
            audioTrack.setPlaybackPositionUpdateListener(this);

            // init All the jitter variables
            initVariables();
            // short[] tempBuf = shortBuffer;//new short[bufferSize / 2];
            audioTrack.write(shortBuffer, 0, shortBuffer.length);
            audioTrack.write(shortBuffer, 0, shortBuffer.length);
            audioTrack.write(shortBuffer, 0, shortBuffer.length);
            audioTrack.write(shortBuffer, 0, shortBuffer.length);
            audioTrack.write(shortBuffer, 0, shortBuffer.length);
            audioTrack.write(shortBuffer, 0, shortBuffer.length);
            // start playback of the audioTrack
            audioTrack.play();

        } else {
            Log.e(LOG_TAG, "Unble to create AudioTrack instance");
        }
    } else {
        Log.e(LOG_TAG, "Unable to get the minimum buffer size");
    }
}

@Override
    public void onPeriodicNotification(AudioTrack track) {
        try {
            fillAudio(shortBuffer);
            track.write(shortBuffer, 0, Constants.FRAME_SIZE / 2);
        } catch (NullPointerException nex) {
            nex.printStackTrace();
            Log.e(LOG_TAG, "Null Pointer inside periodic notification");
        }}

fillAudio() is a function which fills the Buffer...

  1. User clicks on the Video Chat Button which gets the camera using Camera.open(), sets the parameters, callback and later starts the callback by using camera.startPreview()..

OnTouchListener cameraSurfaceOnTouch = new OnTouchListener() { int x = 0; int y = 0; int dx = 0; int dy = 0; boolean moving = false;

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            x = (int) event.getX();
            y = (int) event.getY();
            dx = (int) event.getX() - v.getLeft();
            dy = (int) event.getY() - v.getTop();
            moving = true;

            return true;
        case MotionEvent.ACTION_MOVE:
            if (moving) {
                x = (int) event.getX() - dx;
                y = (int) event.getY() - dy;

                x = Math.max(x, 0);
                x = Math.min(x, getWindowManager().getDefaultDisplay().getWidth() - v.getWidth());

                y = Math.max(y, 0);
                y = Math.min(y, getWindowManager().getDefaultDisplay().getHeight() - v.getHeight());

                v.layout(x, y, x + v.getWidth(), y + v.getHeight());
            }
            return true;
        case MotionEvent.ACTION_UP:
            x = (int) event.getX() - dx;
            y = (int) event.getY() - dy;

            x = Math.max(x, 0);
            x = Math.min(x, getWindowManager().getDefaultDisplay().getWidth() - v.getWidth());

            y = Math.max(y, 0);
            y = Math.min(y, getWindowManager().getDefaultDisplay().getHeight() - v.getHeight());

            // v.layout(x ,y,x + v.getMeasuredWidth() , y
            // +v.getMeasuredHeight());
            moving = false;
            return true;
        }
        // v.invalidate();
        return false;
    }
};

Callback videoPlayerCallBack = new Callback() {
    public void surfaceDestroyed(SurfaceHolder holder) {
        stopCapturerVideo();
        if (converterID != -1 && x264Wrapper != null) {
            x264Wrapper.destroyVideoFormate(converterID);
            converterID = -1;
        }
    }
private void startCapturerVideo() {
        if (m_CameraStatus == false) {
            this.m_CameraStatus = this.videoCapturer.startCamera();
        }
        synchronized (this.m_videoCapturerBufferList) {
            this.m_videoCapturerBufferList.clear();
        }

        byte[] tmp = new byte[10];
        tmp[0] = Constants.VIDEO_SESSION_STARTED;

        short width = 160;
        short height = 120;

        byte[] mIndex = CommonMethods.toByteArray(session.getSelfMeetingIndex());
        byte[] aWidth = CommonMethods.toByteArray(width);
        byte[] aHeight = CommonMethods.toByteArray(height);

        tmp[1] = mIndex[0];
        tmp[2] = mIndex[1];

        tmp[3] = aWidth[0];
        tmp[4] = aWidth[1];

        tmp[5] = aHeight[0];
        tmp[6] = aHeight[1];

        tmp[7] = 0;
        session.add(tmp, 8, 3);

        aWidth = null;
        aHeight = null;
        tmp = null;

        this.stopThread = false;
        this.encodeAndSendThread = new Thread(encodeAndSendRun);
        this.encodeAndSendThread.start();
        this.videoCapturer.startCaptureringVideo();

    }
   public boolean startCaptureringVideo() {
        boolean cameraStatus = true;
        Log.e(LOG_TAG,"startCaptureringVideo called ");
        if(this.mCamera != null)
        {
            try {
//              this.mCamera.setPreviewDisplay(this.videoCaptureViewHolder);
                this.mCamera.startPreview();
                } 
            catch (Throwable e) {
                cameraStatus = false;
                mCamera.release();
                mCamera = null;

                }
        }
        else
        {
            cameraStatus =false;
        }
        return cameraStatus;
    }
  1. onPeriodicNotification() is never called again after step 2 even if I stop and release the camera.

What could be the possible reason for this,

2
We need to see some code here. - Erol
please see the edit... if that can be helpful.. - Amit
sorry I need to see the code that I can give you an proper awnser.. - safari
You are asking us to make guesses and imagine how the code is written. There could be one simple line in your code causing this error and we cannot guess this. It is not really possible to give you working advice without having a look at the code. - Erol
@babatenor please see the latest edits... and tell me if you need any other function... - Amit

2 Answers

5
votes

Check AudioManager's onAudioFocusChange callback:

@Override
public void onAudioFocusChange(int focusChange) {
    if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) {
        //this audio focus change is made when you use the camera
    }
}

Maybe you're pausing the audio when the audio focus is changed, check it out.

1
votes

I had similar problem with camera video recording sound stops after 2 or 3 seconds. I accidently found that it was coused couse in Android phone HTC Desire Z / HTC G2 aka Vision in Android Options in Developer Options in section APPS ive turned on "Dont keep activities" with description Destroy every activity as soon as the user leaves it. When i disabled that then after reboot video recorded all audio. Check yourself maybe you have enabled that option and disable it so no apps are being closed. Some process just shuts down anyway couse it get some status witch means it isnt active and that option makes kill everything no beeing active.