Exemplo n.º 1
0
 /** Release all releated objects */
 protected void release() {
   if (DEBUG) Log.d(TAG, "release:");
   try {
     mListener.onStopped(this);
   } catch (Exception e) {
     Log.e(TAG, "failed onStopped", e);
   }
   mIsCapturing = false;
   if (mMediaCodec != null) {
     try {
       mMediaCodec.stop();
       mMediaCodec.release();
       mMediaCodec = null;
     } catch (Exception e) {
       Log.e(TAG, "failed releasing MediaCodec", e);
     }
   }
   if (mMuxerStarted) {
     final MediaMuxerWrapper muxer = mWeakMuxer.get();
     if (muxer != null) {
       try {
         muxer.stop();
       } catch (Exception e) {
         Log.e(TAG, "failed stopping muxer", e);
       }
     }
   }
   mBufferInfo = null;
 }
Exemplo n.º 2
0
 public MediaEncoder(MediaMuxerWrapper muxer, MediaEncoderListener listener) {
   if (listener == null) throw new NullPointerException("MediaEncoderListener is null");
   if (muxer == null) throw new NullPointerException("MediaMuxerWrapper is null");
   mWeakMuxer = new WeakReference<MediaMuxerWrapper>(muxer);
   muxer.addEncoder(this);
   mListener = listener;
   synchronized (mSync) {
     // create BufferInfo here for effectiveness(to reduce GC)
     mBufferInfo = new MediaCodec.BufferInfo();
     // wait for Handler is ready
     new Thread(this, getClass().getSimpleName()).start();
     try {
       mSync.wait();
     } catch (InterruptedException e) {
     }
   }
 }
Exemplo n.º 3
0
 public String getOutputPath() {
   MediaMuxerWrapper muxer = mWeakMuxer.get();
   return muxer != null ? muxer.getOutputPath() : null;
 }
Exemplo n.º 4
0
  /** drain encoded data and write them to muxer */
  protected void drain() {
    if (mMediaCodec == null) return;
    ByteBuffer[] encoderOutputBuffers = mMediaCodec.getOutputBuffers();
    int encoderStatus, count = 0;
    final MediaMuxerWrapper muxer = mWeakMuxer.get();
    if (muxer == null) {
      //        	throw new NullPointerException("muxer is unexpectedly null");
      Log.w(TAG, "muxer is unexpectedly null");
      return;
    }
    LOOP:
    while (mIsCapturing) {
      // get encoded data with maximum timeout duration of TIMEOUT_USEC(=10[msec])
      encoderStatus = mMediaCodec.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
      if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
        // wait 5 counts(=TIMEOUT_USEC x 5 = 50msec) until data/EOS come
        if (!mIsEOS) {
          if (++count > 5) break LOOP; // out of while
        }
      } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
        if (DEBUG) Log.v(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
        // this shoud not come when encoding
        encoderOutputBuffers = mMediaCodec.getOutputBuffers();
      } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
        if (DEBUG) Log.v(TAG, "INFO_OUTPUT_FORMAT_CHANGED");
        // this status indicate the output format of codec is changed
        // this should come only once before actual encoded data
        // but this status never come on Android4.3 or less
        // and in that case, you should treat when MediaCodec.BUFFER_FLAG_CODEC_CONFIG come.
        if (mMuxerStarted) { // second time request is error
          throw new RuntimeException("format changed twice");
        }
        // get output format from codec and pass them to muxer
        // getOutputFormat should be called after INFO_OUTPUT_FORMAT_CHANGED otherwise crash.
        final MediaFormat format = mMediaCodec.getOutputFormat(); // API >= 16
        mTrackIndex = muxer.addTrack(format);
        mMuxerStarted = true;
        if (!muxer.start()) {
          // we should wait until muxer is ready
          synchronized (muxer) {
            while (!muxer.isStarted())
              try {
                muxer.wait(100);
              } catch (InterruptedException e) {
                break LOOP;
              }
          }
        }
      } else if (encoderStatus < 0) {
        // unexpected status
        if (DEBUG)
          Log.w(TAG, "drain:unexpected result from encoder#dequeueOutputBuffer: " + encoderStatus);
      } else {
        final ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
        if (encodedData == null) {
          // this never should come...may be a MediaCodec internal error
          throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
        }
        if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
          // You shoud set output format to muxer here when you target Android4.3 or less
          // but MediaCodec#getOutputFormat can not call here(because INFO_OUTPUT_FORMAT_CHANGED
          // don't come yet)
          // therefor we should expand and prepare output format from buffer data.
          // This sample is for API>=18(>=Android 4.3), just ignore this flag here
          if (DEBUG) Log.d(TAG, "drain:BUFFER_FLAG_CODEC_CONFIG");
          mBufferInfo.size = 0;
        }

        if (mBufferInfo.size != 0) {
          // encoded data is ready, clear waiting counter
          count = 0;
          if (!mMuxerStarted) {
            // muxer is not ready...this will prrograming failure.
            throw new RuntimeException("drain:muxer hasn't started");
          }
          // write encoded data to muxer(need to adjust presentationTimeUs.
          mBufferInfo.presentationTimeUs = getPTSUs();
          muxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
          prevOutputPTSUs = mBufferInfo.presentationTimeUs;
        }
        // return buffer to encoder
        mMediaCodec.releaseOutputBuffer(encoderStatus, false);
        if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
          // when EOS come.
          mMuxerStarted = mIsCapturing = false;
          break; // out of while
        }
      }
    }
  }