在Android中启用相机时,音频播放会停止吗?

时间:2012-07-24 06:50:48

标签: android audio android-ndk android-camera

我正在开发一款需要音频/视频聊天的应用...我的问题是当我开始捕捉视频时,音频播放完全停止。

技术说明 我使用AudioTrack Class和AudioTrack.OnPlaybackPositionUpdateListener进行音频播放。 我使用Camera和Camera.PreviewCallBack进行视频录制。

现在,一旦相机启动,AudioTrack类的回叫就会停止工作。我该怎么做才能解决这个问题?我有HTC的设备,它有Android2.2。

修改 由于我无法在此发布完整代码...(我无法访问视频模块的代码), 我在这里列出了这个场景: -

  1. 已启动音频聊天且正在播放音频,这意味着onPeriodicNotification()被正确调用..
  2. 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()是一个填充缓冲区的函数......

    1. 用户点击使用Camera.open()获取相机的视频聊天按钮,设置参数,回调以及稍后使用camera.startPreview()启动回调..
    2. 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()也不会在第2步之后再次调用。
      2. 可能的原因是什么,

2 个答案:

答案 0 :(得分:5)

检查AudioManager的onAudioFocusChange回调:

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

当音频焦点发生变化时,可能会暂停音频,请将其检出。

答案 1 :(得分:1)

我有类似的问题,相机视频录制声音停止2或3秒后。 我意外地发现它是安卓手机HTC Desire Z / HTC G2中的视觉功能在开发者选项的Android选项中的视觉APPS我开启了“不要保持活动”的描述在用户离开时立即销毁每个活动。 当我禁用时,然后重新启动后视频录制所有音频。 检查自己可能已启用该选项并禁用它,因此没有关闭应用程序。有些过程无论如何都会关闭它会得到一些状态巫婆意味着它不活跃而且该选项会杀死所有没有活动的东西。