Created
June 18, 2014 20:47
-
-
Save FlyingJester/43b91d439296f52a2e9d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| class MediaCodecData : public MediaData { | |
| mcdecode::Decoder *mDecoder; | |
| int mBuffer; | |
| MediaData::Type mType; | |
| public: | |
| MediaCodecData(MediaData::Type aType,int64_t aOffset,int64_t aTimestamp, | |
| int64_t aDuration, mcdecode::Decoder *aDecoder, int aBuffer) | |
| : MediaData(aType,aOffset,aTimestamp,aDuration) | |
| , mDecoder(aDecoder) | |
| , mBuffer(aBuffer) | |
| , mType(aType) { printf_stderr("We will want to release buffer %i at some point.\n", aBuffer);} | |
| virtual ~MediaCodecData(){ | |
| printf_stderr("Media Codec: Releaseing output buffer number %i...\n", mBuffer); | |
| mDecoder->ReleaseOutputBuffer(mBuffer, false); | |
| printf_stderr("Media Codec: Released output buffer number %i successfully.\n", mBuffer); | |
| } | |
| }; | |
| // Auto-free MC resources | |
| MediaCodecBuffer::MediaCodecBuffer() | |
| { | |
| mDecoder = nullptr; | |
| mBufferIndex = -1; | |
| } | |
| MediaCodecBuffer::MediaCodecBuffer(int32_t aBufferIndex, int32_t aOffset, | |
| int32_t aSize, int32_t aTime, | |
| int32_t aFlags, mcdecode::Decoder *aDecoder) | |
| { | |
| mDecoder = aDecoder; | |
| mBufferIndex = aBufferIndex; | |
| mOffset = aOffset; | |
| mSize = aSize; | |
| mTime = aTime; | |
| mFlags = aFlags; | |
| } | |
| MediaCodecBuffer::~MediaCodecBuffer() | |
| { | |
| printf_stderr("Media Codec: Queueing inputbuffer %i from AutoPtr.\n", mBufferIndex); | |
| printf_stderr("Media Codec: Stats: mOffset %i\tmSize %i\tmTime %i\tmFlags %i (FLAGS NOT suppressed to 0 in actual call).\n", mOffset, mSize, mTime, mFlags); | |
| if( (mDecoder != nullptr) && (mBufferIndex >= 0) ){ | |
| mDecoder->QueueInputBuffer(mBufferIndex, mOffset, mSize, mTime, mFlags); | |
| printf_stderr("Media Codec: Inputbuffer %i queued successfuly.\n", mBufferIndex); | |
| } | |
| else | |
| printf_stderr("Media Codec: Decided not to queue inputbuffer %i\n", mBufferIndex); | |
| } | |
| nsresult AndroidInputLoader::Run(){ | |
| printf_stderr("Media Codec: Run is starting!\n"); | |
| int lInputIndex = mDecoder->DequeueInputBuffer(-1); | |
| printf_stderr("Media Codec: DequeueInputBuffer has completed.\n"); | |
| // Don't worry, aSample. This smart pointer will...take care...of you. | |
| nsAutoPtr<mp4_demuxer::MP4Sample> apSample(mSample); | |
| // Until we chose to forget, any return means we had errors. | |
| nsAutoPtr<ErrorCaller<MediaDataDecoderCallback> > lErrorCallback( | |
| new ErrorCaller<MediaDataDecoderCallback>(mCallback)); | |
| if(lInputIndex<0){ | |
| return NS_ERROR_NOT_AVAILABLE; | |
| } | |
| // Ensures that the buffer at the dequeued index is returned to MediaCodec. | |
| // The size is set to zero until we know how large of a buffer we have. | |
| // This ensures that if we return before we are sure we are in bounds, | |
| // we won't crash from the Java side. | |
| nsAutoPtr<MediaCodecBuffer> lAutoInputBuffer(new MediaCodecBuffer( | |
| lInputIndex, 0, 0, 1, | |
| ((mSample->is_sync_point)?MediaCodec::getBUFFER_FLAG_SYNC_FRAME():0), | |
| mDecoder)); | |
| printf_stderr("Media Codec: Asking for JNI environment.\n"); | |
| JNIEnv *aJEnv = GetJNIForThread(); | |
| printf_stderr("Media Codec: Got JNI environment.\n"); | |
| if(aJEnv == nullptr){ | |
| return NS_ERROR_FAILURE; | |
| } | |
| mInputBuffers = mDecoder->GetInputBuffers(); | |
| mOutputBuffers = mDecoder->GetOutputBuffers(); | |
| printf_stderr("Media Codec: Inside the input loader, the Input buffer is %p and the Output buffer is %p.\n", mInputBuffers, mOutputBuffers); | |
| { | |
| int bufferNum = aJEnv->GetArrayLength(mInputBuffers); | |
| printf_stderr("Media Codec: The input buffer array is %i buffers long.\n", bufferNum); | |
| } | |
| jobject lJInBuffer = aJEnv->GetObjectArrayElement(mInputBuffers, | |
| lInputIndex); | |
| printf_stderr("Media Codec: Got the buffer.\n"); | |
| if(lJInBuffer == nullptr){ | |
| return NS_ERROR_FAILURE; | |
| } | |
| MCByteBuffer *lInBuffer = MCByteBuffer::Wrap(lJInBuffer); | |
| if(lInBuffer==nullptr){ | |
| return NS_ERROR_FAILURE; | |
| } | |
| size_t lMaximumPayload = lInBuffer->GetCapacity(); | |
| printf_stderr("Media Codec: Got the buffer's capacity.\n"); | |
| if(lMaximumPayload>mSample->size) | |
| lMaximumPayload=mSample->size; | |
| printf_stderr("Media Codec: The maximum payload was %i. The max of %i" | |
| " (sample) and %i (buffer)\n", lMaximumPayload, | |
| mSample->size, lInBuffer->GetCapacity()); | |
| lAutoInputBuffer->mSize = lMaximumPayload; | |
| // If we are lucky the buffer is backed with a native array. Then we can | |
| // write directly into its raw buffer. | |
| // TODO: Find out why this is crashing. | |
| void *rawBuffer = nullptr; | |
| if(lJInBuffer!=nullptr && lInBuffer->IsDirect() && false) | |
| rawBuffer = aJEnv->GetDirectBufferAddress(lJInBuffer); | |
| if(rawBuffer != nullptr){ | |
| //Fill the input buffer. | |
| memcpy(rawBuffer, mSample->data, lMaximumPayload); | |
| } | |
| else{ | |
| // We have to make do by slowly placing the pieces in one after another | |
| // Do this in chunks of 8 bytes until there are < 8 bytes eft, put the | |
| // remains in by char. | |
| //delete lInBuffer; | |
| //mozilla::widget::android::ByteBuffer *lByteBuffer = mozilla::widget::android::ByteBuffer::Wrap(lJInBuffer); | |
| if(lInBuffer == nullptr){ | |
| return NS_ERROR_FAILURE; | |
| } | |
| size_t i = 0; | |
| for(; i < lMaximumPayload; i+=sizeof(int64_t)){ | |
| lInBuffer->PutLong(i, mSample->data[i]); | |
| } | |
| for(; i < lMaximumPayload; i++){ | |
| lInBuffer->PutChar1(i, mSample->data[i]); | |
| } | |
| } | |
| printf_stderr("Media Codec: Ride it out at %s %i.\n", | |
| __func__, __LINE__); | |
| // Input successfully placed. We don't need to worry about this anymore. | |
| lErrorCallback->forget(); | |
| //delete lAutoInputBuffer.forget(); | |
| // mDecoder->QueueInputBuffer(lInputIndex, 0, lMaximumPayload, 1000000, (mSample->is_sync_point)?MediaCodec::getBUFFER_FLAG_SYNC_FRAME():0); | |
| //printf_stderr("Media Codec: Inputbuffer %i queued successfuly.\n", lInputIndex); | |
| // Check to see if we can get any output: | |
| int lOutputIndex; | |
| do{ | |
| BufferInfo *lInfo = new BufferInfo(); | |
| lOutputIndex = mDecoder->DequeueOutputBuffer(nullptr, 1000000); | |
| printf_stderr("Media Codec: The output buffer we got is %i\n", lOutputIndex); | |
| if(lOutputIndex == MediaCodec::getINFO_OUTPUT_BUFFERS_CHANGED()){ | |
| printf_stderr("Media Codec: The output buffers have moved. Old location %p\n", mOutputBuffers); | |
| mOutputBuffers = mDecoder->GetOutputBuffers(); | |
| printf_stderr("Media Codec: The output buffers have moved. New location %p\n", mOutputBuffers); | |
| continue; | |
| } | |
| if(lOutputIndex<0){ | |
| printf_stderr("Media Codec: Announcing out of input.\n"); | |
| mCallback->InputExhausted(); | |
| continue; | |
| } | |
| /* | |
| enum Type { | |
| AUDIO_SAMPLES = 0, | |
| VIDEO_FRAME = 1 | |
| }; | |
| */ | |
| printf_stderr("Media Codec: Announcing output.\n"); | |
| mCallback->Output( | |
| new MediaCodecData(mType, 0, mSample->composition_timestamp, | |
| mSample->duration, mDecoder, lOutputIndex)); | |
| } while(lOutputIndex>=0); | |
| printf_stderr("Media Codec: Riding out Input.\n"); | |
| return NS_OK; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment