Loading media/libmediaplayerservice/MetadataRetrieverClient.cpp +0 −4 Original line number Original line Diff line number Diff line Loading @@ -48,7 +48,6 @@ MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid) { { ALOGV("MetadataRetrieverClient constructor pid(%d)", pid); ALOGV("MetadataRetrieverClient constructor pid(%d)", pid); mPid = pid; mPid = pid; mThumbnail = NULL; mAlbumArt = NULL; mAlbumArt = NULL; mRetriever = NULL; mRetriever = NULL; } } Loading Loading @@ -77,7 +76,6 @@ void MetadataRetrieverClient::disconnect() ALOGV("disconnect from pid %d", mPid); ALOGV("disconnect from pid %d", mPid); Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock); mRetriever.clear(); mRetriever.clear(); mThumbnail.clear(); mAlbumArt.clear(); mAlbumArt.clear(); IPCThreadState::self()->flushCommands(); IPCThreadState::self()->flushCommands(); } } Loading Loading @@ -201,7 +199,6 @@ sp<IMemory> MetadataRetrieverClient::getFrameAtTime( (long long)timeUs, option, colorFormat, metaOnly); (long long)timeUs, option, colorFormat, metaOnly); Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock); Mutex::Autolock glock(sLock); Mutex::Autolock glock(sLock); mThumbnail.clear(); if (mRetriever == NULL) { if (mRetriever == NULL) { ALOGE("retriever is not initialized"); ALOGE("retriever is not initialized"); return NULL; return NULL; Loading @@ -220,7 +217,6 @@ sp<IMemory> MetadataRetrieverClient::getImageAtIndex( index, colorFormat, metaOnly, thumbnail); index, colorFormat, metaOnly, thumbnail); Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock); Mutex::Autolock glock(sLock); Mutex::Autolock glock(sLock); mThumbnail.clear(); if (mRetriever == NULL) { if (mRetriever == NULL) { ALOGE("retriever is not initialized"); ALOGE("retriever is not initialized"); return NULL; return NULL; Loading media/libmediaplayerservice/MetadataRetrieverClient.h +1 −2 Original line number Original line Diff line number Diff line Loading @@ -73,9 +73,8 @@ private: sp<MediaMetadataRetrieverBase> mRetriever; sp<MediaMetadataRetrieverBase> mRetriever; pid_t mPid; pid_t mPid; // Keep the shared memory copy of album art and capture frame (for thumbnail) // Keep the shared memory copy of album art sp<IMemory> mAlbumArt; sp<IMemory> mAlbumArt; sp<IMemory> mThumbnail; }; }; }; // namespace android }; // namespace android Loading media/libstagefright/FrameDecoder.cpp +146 −130 Original line number Original line Diff line number Diff line Loading @@ -42,7 +42,6 @@ namespace android { static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec static const size_t kRetryCount = 50; // must be >0 static const size_t kRetryCount = 50; // must be >0 //static sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta, sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta, int32_t width, int32_t height, int32_t dstBpp, bool metaOnly = false) { int32_t width, int32_t height, int32_t dstBpp, bool metaOnly = false) { int32_t rotationAngle; int32_t rotationAngle; Loading Loading @@ -94,7 +93,6 @@ sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta, return frameMem; return frameMem; } } //static bool findThumbnailInfo( bool findThumbnailInfo( const sp<MetaData> &trackMeta, int32_t *width, int32_t *height, const sp<MetaData> &trackMeta, int32_t *width, int32_t *height, uint32_t *type = NULL, const void **data = NULL, size_t *size = NULL) { uint32_t *type = NULL, const void **data = NULL, size_t *size = NULL) { Loading @@ -107,30 +105,15 @@ bool findThumbnailInfo( type ?: &dummyType, data ?: &dummyData, size ?: &dummySize); type ?: &dummyType, data ?: &dummyData, size ?: &dummySize); } } //static bool findGridInfo(const sp<MetaData> &trackMeta, sp<IMemory> FrameDecoder::getMetadataOnly( int32_t *tileWidth, int32_t *tileHeight, int32_t *gridRows, int32_t *gridCols) { const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail) { return trackMeta->findInt32(kKeyTileWidth, tileWidth) && (*tileWidth > 0) OMX_COLOR_FORMATTYPE dstFormat; && trackMeta->findInt32(kKeyTileHeight, tileHeight) && (*tileHeight > 0) int32_t dstBpp; && trackMeta->findInt32(kKeyGridRows, gridRows) && (*gridRows > 0) if (!getDstColorFormat( && trackMeta->findInt32(kKeyGridCols, gridCols) && (*gridCols > 0); (android_pixel_format_t)colorFormat, &dstFormat, &dstBpp)) { return NULL; } } int32_t width, height; bool getDstColorFormat( if (thumbnail) { if (!findThumbnailInfo(trackMeta, &width, &height)) { return NULL; } } else { CHECK(trackMeta->findInt32(kKeyWidth, &width)); CHECK(trackMeta->findInt32(kKeyHeight, &height)); } return allocVideoFrame(trackMeta, width, height, dstBpp, true /*metaOnly*/); } //static bool FrameDecoder::getDstColorFormat( android_pixel_format_t colorFormat, android_pixel_format_t colorFormat, OMX_COLOR_FORMATTYPE *dstFormat, OMX_COLOR_FORMATTYPE *dstFormat, int32_t *dstBpp) { int32_t *dstBpp) { Loading Loading @@ -162,46 +145,57 @@ bool FrameDecoder::getDstColorFormat( return false; return false; } } sp<IMemory> FrameDecoder::extractFrame( //static int64_t frameTimeUs, int option, int colorFormat) { sp<IMemory> FrameDecoder::getMetadataOnly( const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail) { OMX_COLOR_FORMATTYPE dstFormat; int32_t dstBpp; if (!getDstColorFormat( if (!getDstColorFormat( (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) { (android_pixel_format_t)colorFormat, &dstFormat, &dstBpp)) { return NULL; return NULL; } } status_t err = extractInternal(frameTimeUs, 1, option); int32_t width, height; if (err != OK) { if (thumbnail) { if (!findThumbnailInfo(trackMeta, &width, &height)) { return NULL; return NULL; } } } else { return mFrames.size() > 0 ? mFrames[0] : NULL; CHECK(trackMeta->findInt32(kKeyWidth, &width)); CHECK(trackMeta->findInt32(kKeyHeight, &height)); } } return allocVideoFrame(trackMeta, width, height, dstBpp, true /*metaOnly*/); status_t FrameDecoder::extractFrames( int64_t frameTimeUs, size_t numFrames, int option, int colorFormat, std::vector<sp<IMemory> >* frames) { if (!getDstColorFormat( (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) { return ERROR_UNSUPPORTED; } } status_t err = extractInternal(frameTimeUs, numFrames, option); FrameDecoder::FrameDecoder( if (err != OK) { const AString &componentName, return err; const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : mComponentName(componentName), mTrackMeta(trackMeta), mSource(source), mDstFormat(OMX_COLOR_Format16bitRGB565), mDstBpp(2), mHaveMoreInputs(true), mFirstSample(true) { } } for (size_t i = 0; i < mFrames.size(); i++) { FrameDecoder::~FrameDecoder() { frames->push_back(mFrames[i]); if (mDecoder != NULL) { mDecoder->release(); mSource->stop(); } } return OK; } } status_t FrameDecoder::extractInternal( status_t FrameDecoder::init( int64_t frameTimeUs, size_t numFrames, int option) { int64_t frameTimeUs, size_t numFrames, int option, int colorFormat) { if (!getDstColorFormat( (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) { return ERROR_UNSUPPORTED; } MediaSource::ReadOptions options; sp<AMessage> videoFormat = onGetFormatAndSeekOptions( sp<AMessage> videoFormat = onGetFormatAndSeekOptions( frameTimeUs, numFrames, option, &options); frameTimeUs, numFrames, option, &mReadOptions); if (videoFormat == NULL) { if (videoFormat == NULL) { ALOGE("video format or seek mode not supported"); ALOGE("video format or seek mode not supported"); return ERROR_UNSUPPORTED; return ERROR_UNSUPPORTED; Loading @@ -217,7 +211,8 @@ status_t FrameDecoder::extractInternal( return (decoder.get() == NULL) ? NO_MEMORY : err; return (decoder.get() == NULL) ? NO_MEMORY : err; } } err = decoder->configure(videoFormat, NULL /* surface */, NULL /* crypto */, 0 /* flags */); err = decoder->configure( videoFormat, NULL /* surface */, NULL /* crypto */, 0 /* flags */); if (err != OK) { if (err != OK) { ALOGW("configure returned error %d (%s)", err, asString(err)); ALOGW("configure returned error %d (%s)", err, asString(err)); decoder->release(); decoder->release(); Loading @@ -237,43 +232,46 @@ status_t FrameDecoder::extractInternal( decoder->release(); decoder->release(); return err; return err; } } mDecoder = decoder; Vector<sp<MediaCodecBuffer> > inputBuffers; return OK; err = decoder->getInputBuffers(&inputBuffers); } sp<IMemory> FrameDecoder::extractFrame() { status_t err = extractInternal(); if (err != OK) { if (err != OK) { ALOGW("failed to get input buffers: %d (%s)", err, asString(err)); return NULL; decoder->release(); mSource->stop(); return err; } } Vector<sp<MediaCodecBuffer> > outputBuffers; return mFrames.size() > 0 ? mFrames[0] : NULL; err = decoder->getOutputBuffers(&outputBuffers); } status_t FrameDecoder::extractFrames(std::vector<sp<IMemory> >* frames) { status_t err = extractInternal(); if (err != OK) { if (err != OK) { ALOGW("failed to get output buffers: %d (%s)", err, asString(err)); decoder->release(); mSource->stop(); return err; return err; } } sp<AMessage> outputFormat = NULL; for (size_t i = 0; i < mFrames.size(); i++) { bool haveMoreInputs = true; frames->push_back(mFrames[i]); size_t index, offset, size; } int64_t timeUs; return OK; size_t retriesLeft = kRetryCount; } status_t FrameDecoder::extractInternal() { status_t err = OK; bool done = false; bool done = false; bool firstSample = true; size_t retriesLeft = kRetryCount; do { do { size_t inputIndex = -1; size_t index; int64_t ptsUs = 0ll; int64_t ptsUs = 0ll; uint32_t flags = 0; uint32_t flags = 0; sp<MediaCodecBuffer> codecBuffer = NULL; // Queue as many inputs as we possibly can, then block on dequeuing // Queue as many inputs as we possibly can, then block on dequeuing // outputs. After getting each output, come back and queue the inputs // outputs. After getting each output, come back and queue the inputs // again to keep the decoder busy. // again to keep the decoder busy. while (haveMoreInputs) { while (mHaveMoreInputs) { err = decoder->dequeueInputBuffer(&inputIndex, 0); err = mDecoder->dequeueInputBuffer(&index, 0); if (err != OK) { if (err != OK) { ALOGV("Timed out waiting for input"); ALOGV("Timed out waiting for input"); if (retriesLeft) { if (retriesLeft) { Loading @@ -281,16 +279,21 @@ status_t FrameDecoder::extractInternal( } } break; break; } } codecBuffer = inputBuffers[inputIndex]; sp<MediaCodecBuffer> codecBuffer; err = mDecoder->getInputBuffer(index, &codecBuffer); if (err != OK) { ALOGE("failed to get input buffer %zu", index); break; } MediaBufferBase *mediaBuffer = NULL; MediaBufferBase *mediaBuffer = NULL; err = mSource->read(&mediaBuffer, &options); err = mSource->read(&mediaBuffer, &mReadOptions); options.clearSeekTo(); mReadOptions.clearSeekTo(); if (err != OK) { if (err != OK) { ALOGW("Input Error or EOS"); ALOGW("Input Error or EOS"); haveMoreInputs = false; mHaveMoreInputs = false; if (!firstSample && err == ERROR_END_OF_STREAM) { if (!mFirstSample && err == ERROR_END_OF_STREAM) { err = OK; err = OK; } } break; break; Loading @@ -299,7 +302,7 @@ status_t FrameDecoder::extractInternal( if (mediaBuffer->range_length() > codecBuffer->capacity()) { if (mediaBuffer->range_length() > codecBuffer->capacity()) { ALOGE("buffer size (%zu) too large for codec input size (%zu)", ALOGE("buffer size (%zu) too large for codec input size (%zu)", mediaBuffer->range_length(), codecBuffer->capacity()); mediaBuffer->range_length(), codecBuffer->capacity()); haveMoreInputs = false; mHaveMoreInputs = false; err = BAD_VALUE; err = BAD_VALUE; } else { } else { codecBuffer->setRange(0, mediaBuffer->range_length()); codecBuffer->setRange(0, mediaBuffer->range_length()); Loading @@ -309,45 +312,46 @@ status_t FrameDecoder::extractInternal( (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(), (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(), mediaBuffer->range_length()); mediaBuffer->range_length()); onInputReceived(codecBuffer, mediaBuffer->meta_data(), firstSample, &flags); onInputReceived(codecBuffer, mediaBuffer->meta_data(), mFirstSample, &flags); firstSample = false; mFirstSample = false; } } mediaBuffer->release(); mediaBuffer->release(); if (haveMoreInputs && inputIndex < inputBuffers.size()) { if (mHaveMoreInputs) { ALOGV("QueueInput: size=%zu ts=%" PRId64 " us flags=%x", ALOGV("QueueInput: size=%zu ts=%" PRId64 " us flags=%x", codecBuffer->size(), ptsUs, flags); codecBuffer->size(), ptsUs, flags); err = decoder->queueInputBuffer( err = mDecoder->queueInputBuffer( inputIndex, index, codecBuffer->offset(), codecBuffer->offset(), codecBuffer->size(), codecBuffer->size(), ptsUs, ptsUs, flags); flags); if (flags & MediaCodec::BUFFER_FLAG_EOS) { if (flags & MediaCodec::BUFFER_FLAG_EOS) { haveMoreInputs = false; mHaveMoreInputs = false; } } } } } } while (err == OK) { while (err == OK) { size_t offset, size; // wait for a decoded buffer // wait for a decoded buffer err = decoder->dequeueOutputBuffer( err = mDecoder->dequeueOutputBuffer( &index, &index, &offset, &offset, &size, &size, &timeUs, &ptsUs, &flags, &flags, kBufferTimeOutUs); kBufferTimeOutUs); if (err == INFO_FORMAT_CHANGED) { if (err == INFO_FORMAT_CHANGED) { ALOGV("Received format change"); ALOGV("Received format change"); err = decoder->getOutputFormat(&outputFormat); err = mDecoder->getOutputFormat(&mOutputFormat); } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { ALOGV("Output buffers changed"); ALOGV("Output buffers changed"); err = decoder->getOutputBuffers(&outputBuffers); err = OK; } else { } else { if (err == -EAGAIN /* INFO_TRY_AGAIN_LATER */ && --retriesLeft > 0) { if (err == -EAGAIN /* INFO_TRY_AGAIN_LATER */ && --retriesLeft > 0) { ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft); ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft); Loading @@ -355,12 +359,15 @@ status_t FrameDecoder::extractInternal( } else if (err == OK) { } else if (err == OK) { // If we're seeking with CLOSEST option and obtained a valid targetTimeUs // If we're seeking with CLOSEST option and obtained a valid targetTimeUs // from the extractor, decode to the specified frame. Otherwise we're done. // from the extractor, decode to the specified frame. Otherwise we're done. ALOGV("Received an output buffer, timeUs=%lld", (long long)timeUs); ALOGV("Received an output buffer, timeUs=%lld", (long long)ptsUs); sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index); sp<MediaCodecBuffer> videoFrameBuffer; err = mDecoder->getOutputBuffer(index, &videoFrameBuffer); err = onOutputReceived(videoFrameBuffer, outputFormat, timeUs, &done); if (err != OK) { ALOGE("failed to get output buffer %zu", index); decoder->releaseOutputBuffer(index); break; } err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done); mDecoder->releaseOutputBuffer(index); } else { } else { ALOGW("Received error %d (%s) instead of output", err, asString(err)); ALOGW("Received error %d (%s) instead of output", err, asString(err)); done = true; done = true; Loading @@ -370,9 +377,6 @@ status_t FrameDecoder::extractInternal( } } } while (err == OK && !done); } while (err == OK && !done); mSource->stop(); decoder->release(); if (err != OK) { if (err != OK) { ALOGE("failed to get video frame (err %d)", err); ALOGE("failed to get video frame (err %d)", err); } } Loading @@ -380,6 +384,20 @@ status_t FrameDecoder::extractInternal( return err; return err; } } ////////////////////////////////////////////////////////////////////// VideoFrameDecoder::VideoFrameDecoder( const AString &componentName, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : FrameDecoder(componentName, trackMeta, source), mIsAvcOrHevc(false), mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC), mTargetTimeUs(-1ll), mNumFrames(0), mNumFramesDecoded(0) { } sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions( sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions( int64_t frameTimeUs, size_t numFrames, int seekMode, MediaSource::ReadOptions *options) { int64_t frameTimeUs, size_t numFrames, int seekMode, MediaSource::ReadOptions *options) { mSeekMode = static_cast<MediaSource::ReadOptions::SeekMode>(seekMode); mSeekMode = static_cast<MediaSource::ReadOptions::SeekMode>(seekMode); Loading Loading @@ -511,33 +529,47 @@ status_t VideoFrameDecoder::onOutputReceived( return ERROR_UNSUPPORTED; return ERROR_UNSUPPORTED; } } //////////////////////////////////////////////////////////////////////// ImageDecoder::ImageDecoder( const AString &componentName, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : FrameDecoder(componentName, trackMeta, source), mFrame(NULL), mWidth(0), mHeight(0), mGridRows(1), mGridCols(1), mTilesDecoded(0) { } sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( int64_t frameTimeUs, size_t /*numFrames*/, int64_t frameTimeUs, size_t /*numFrames*/, int /*seekMode*/, MediaSource::ReadOptions *options) { int /*seekMode*/, MediaSource::ReadOptions *options) { sp<MetaData> overrideMeta; sp<MetaData> overrideMeta; mThumbnail = false; if (frameTimeUs < 0) { if (frameTimeUs < 0) { uint32_t type; uint32_t type; const void *data; const void *data; size_t size; size_t size; int32_t thumbWidth, thumbHeight; // if we have a stand-alone thumbnail, set up the override meta, // if we have a stand-alone thumbnail, set up the override meta, // and set seekTo time to -1. // and set seekTo time to -1. if (!findThumbnailInfo(trackMeta(), if (!findThumbnailInfo(trackMeta(), &mWidth, &mHeight, &type, &data, &size)) { &thumbWidth, &thumbHeight, &type, &data, &size)) { ALOGE("Thumbnail not available"); ALOGE("Thumbnail not available"); return NULL; return NULL; } } overrideMeta = new MetaData(*(trackMeta())); overrideMeta = new MetaData(*(trackMeta())); overrideMeta->remove(kKeyDisplayWidth); overrideMeta->remove(kKeyDisplayWidth); overrideMeta->remove(kKeyDisplayHeight); overrideMeta->remove(kKeyDisplayHeight); overrideMeta->setInt32(kKeyWidth, thumbWidth); overrideMeta->setInt32(kKeyWidth, mWidth); overrideMeta->setInt32(kKeyHeight, thumbHeight); overrideMeta->setInt32(kKeyHeight, mHeight); overrideMeta->setData(kKeyHVCC, type, data, size); overrideMeta->setData(kKeyHVCC, type, data, size); options->setSeekTo(-1); options->setSeekTo(-1); mThumbnail = true; } else { } else { CHECK(trackMeta()->findInt32(kKeyWidth, &mWidth)); CHECK(trackMeta()->findInt32(kKeyHeight, &mHeight)); options->setSeekTo(frameTimeUs); options->setSeekTo(frameTimeUs); } } Loading @@ -545,17 +577,10 @@ sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( if (overrideMeta == NULL) { if (overrideMeta == NULL) { // check if we're dealing with a tiled heif // check if we're dealing with a tiled heif int32_t tileWidth, tileHeight, gridRows, gridCols; int32_t tileWidth, tileHeight, gridRows, gridCols; if (trackMeta()->findInt32(kKeyTileWidth, &tileWidth) && tileWidth > 0 if (findGridInfo(trackMeta(), &tileWidth, &tileHeight, &gridRows, &gridCols)) { && trackMeta()->findInt32(kKeyTileHeight, &tileHeight) && tileHeight > 0 if (mWidth <= tileWidth * gridCols && mHeight <= tileHeight * gridRows) { && trackMeta()->findInt32(kKeyGridRows, &gridRows) && gridRows > 0 && trackMeta()->findInt32(kKeyGridCols, &gridCols) && gridCols > 0) { int32_t width, height; CHECK(trackMeta()->findInt32(kKeyWidth, &width)); CHECK(trackMeta()->findInt32(kKeyHeight, &height)); if (width <= tileWidth * gridCols && height <= tileHeight * gridRows) { ALOGV("grid: %dx%d, tile size: %dx%d, picture size: %dx%d", ALOGV("grid: %dx%d, tile size: %dx%d, picture size: %dx%d", gridCols, gridRows, tileWidth, tileHeight, width, height); gridCols, gridRows, tileWidth, tileHeight, mWidth, mHeight); overrideMeta = new MetaData(*(trackMeta())); overrideMeta = new MetaData(*(trackMeta())); overrideMeta->setInt32(kKeyWidth, tileWidth); overrideMeta->setInt32(kKeyWidth, tileWidth); Loading @@ -563,8 +588,8 @@ sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( mGridCols = gridCols; mGridCols = gridCols; mGridRows = gridRows; mGridRows = gridRows; } else { } else { ALOGE("bad grid: %dx%d, tile size: %dx%d, picture size: %dx%d", ALOGE("ignore bad grid: %dx%d, tile size: %dx%d, picture size: %dx%d", gridCols, gridRows, tileWidth, tileHeight, width, height); gridCols, gridRows, tileWidth, tileHeight, mWidth, mHeight); } } } } if (overrideMeta == NULL) { if (overrideMeta == NULL) { Loading Loading @@ -600,17 +625,8 @@ status_t ImageDecoder::onOutputReceived( CHECK(outputFormat->findInt32("width", &width)); CHECK(outputFormat->findInt32("width", &width)); CHECK(outputFormat->findInt32("height", &height)); CHECK(outputFormat->findInt32("height", &height)); int32_t imageWidth, imageHeight; if (mThumbnail) { CHECK(trackMeta()->findInt32(kKeyThumbnailWidth, &imageWidth)); CHECK(trackMeta()->findInt32(kKeyThumbnailHeight, &imageHeight)); } else { CHECK(trackMeta()->findInt32(kKeyWidth, &imageWidth)); CHECK(trackMeta()->findInt32(kKeyHeight, &imageHeight)); } if (mFrame == NULL) { if (mFrame == NULL) { sp<IMemory> frameMem = allocVideoFrame(trackMeta(), imageWidth, imageHeight, dstBpp()); sp<IMemory> frameMem = allocVideoFrame(trackMeta(), mWidth, mHeight, dstBpp()); mFrame = static_cast<VideoFrame*>(frameMem->pointer()); mFrame = static_cast<VideoFrame*>(frameMem->pointer()); addFrame(frameMem); addFrame(frameMem); Loading Loading @@ -638,12 +654,12 @@ status_t ImageDecoder::onOutputReceived( // apply crop on bottom-right // apply crop on bottom-right // TODO: need to move this into the color converter itself. // TODO: need to move this into the color converter itself. if (dstRight >= imageWidth) { if (dstRight >= mWidth) { crop_right = imageWidth - dstLeft - 1; crop_right = mWidth - dstLeft - 1; dstRight = dstLeft + crop_right; dstRight = dstLeft + crop_right; } } if (dstBottom >= imageHeight) { if (dstBottom >= mHeight) { crop_bottom = imageHeight - dstTop - 1; crop_bottom = mHeight - dstTop - 1; dstBottom = dstTop + crop_bottom; dstBottom = dstTop + crop_bottom; } } Loading media/libstagefright/StagefrightMetadataRetriever.cpp +17 −14 Original line number Original line Diff line number Diff line Loading @@ -193,12 +193,14 @@ sp<IMemory> StagefrightMetadataRetriever::getImageAtIndex( for (size_t i = 0; i < matchingCodecs.size(); ++i) { for (size_t i = 0; i < matchingCodecs.size(); ++i) { const AString &componentName = matchingCodecs[i]; const AString &componentName = matchingCodecs[i]; ImageDecoder decoder(componentName, trackMeta, source); ImageDecoder decoder(componentName, trackMeta, source); sp<IMemory> frame = decoder.extractFrame( int64_t frameTimeUs = thumbnail ? -1 : 0; thumbnail ? -1 : 0 /*frameTimeUs*/, 0 /*seekMode*/, colorFormat); if (decoder.init(frameTimeUs, 1 /*numFrames*/, 0 /*option*/, colorFormat) == OK) { sp<IMemory> frame = decoder.extractFrame(); if (frame != NULL) { if (frame != NULL) { return frame; return frame; } } } ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str()); ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str()); } } Loading Loading @@ -307,18 +309,19 @@ status_t StagefrightMetadataRetriever::getFrameInternal( for (size_t i = 0; i < matchingCodecs.size(); ++i) { for (size_t i = 0; i < matchingCodecs.size(); ++i) { const AString &componentName = matchingCodecs[i]; const AString &componentName = matchingCodecs[i]; VideoFrameDecoder decoder(componentName, trackMeta, source); VideoFrameDecoder decoder(componentName, trackMeta, source); if (decoder.init(timeUs, numFrames, option, colorFormat) == OK) { if (outFrame != NULL) { if (outFrame != NULL) { *outFrame = decoder.extractFrame(timeUs, option, colorFormat); *outFrame = decoder.extractFrame(); if (*outFrame != NULL) { if (*outFrame != NULL) { return OK; return OK; } } } else if (outFrames != NULL) { } else if (outFrames != NULL) { status_t err = decoder.extractFrames( status_t err = decoder.extractFrames(outFrames); timeUs, numFrames, option, colorFormat, outFrames); if (err == OK) { if (err == OK) { return OK; return OK; } } } } } ALOGV("%s failed to extract frame, trying next decoder.", componentName.c_str()); ALOGV("%s failed to extract frame, trying next decoder.", componentName.c_str()); } } Loading media/libstagefright/include/FrameDecoder.h +18 −32 Original line number Original line Diff line number Diff line Loading @@ -32,32 +32,26 @@ struct AMessage; class MediaCodecBuffer; class MediaCodecBuffer; class IMediaSource; class IMediaSource; class VideoFrame; class VideoFrame; struct MediaCodec; struct FrameDecoder { struct FrameDecoder { FrameDecoder( FrameDecoder( const AString &componentName, const AString &componentName, const sp<MetaData> &trackMeta, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : const sp<IMediaSource> &source); mComponentName(componentName), mTrackMeta(trackMeta), mSource(source), mDstFormat(OMX_COLOR_Format16bitRGB565), mDstBpp(2) {} sp<IMemory> extractFrame(int64_t frameTimeUs, int option, int colorFormat); status_t init( int64_t frameTimeUs, size_t numFrames, int option, int colorFormat); status_t extractFrames( sp<IMemory> extractFrame(); int64_t frameTimeUs, size_t numFrames, status_t extractFrames(std::vector<sp<IMemory> >* frames); int option, int colorFormat, std::vector<sp<IMemory> >* frames); static sp<IMemory> getMetadataOnly( static sp<IMemory> getMetadataOnly( const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail = false); const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail = false); protected: protected: virtual ~FrameDecoder() {} virtual ~FrameDecoder(); virtual sp<AMessage> onGetFormatAndSeekOptions( virtual sp<AMessage> onGetFormatAndSeekOptions( int64_t frameTimeUs, int64_t frameTimeUs, Loading Loading @@ -92,13 +86,13 @@ private: OMX_COLOR_FORMATTYPE mDstFormat; OMX_COLOR_FORMATTYPE mDstFormat; int32_t mDstBpp; int32_t mDstBpp; std::vector<sp<IMemory> > mFrames; std::vector<sp<IMemory> > mFrames; MediaSource::ReadOptions mReadOptions; sp<MediaCodec> mDecoder; sp<AMessage> mOutputFormat; bool mHaveMoreInputs; bool mFirstSample; static bool getDstColorFormat( status_t extractInternal(); android_pixel_format_t colorFormat, OMX_COLOR_FORMATTYPE *dstFormat, int32_t *dstBpp); status_t extractInternal(int64_t frameTimeUs, size_t numFrames, int option); DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder); DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder); }; }; Loading @@ -107,13 +101,7 @@ struct VideoFrameDecoder : public FrameDecoder { VideoFrameDecoder( VideoFrameDecoder( const AString &componentName, const AString &componentName, const sp<MetaData> &trackMeta, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : const sp<IMediaSource> &source); FrameDecoder(componentName, trackMeta, source), mIsAvcOrHevc(false), mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC), mTargetTimeUs(-1ll), mNumFrames(0), mNumFramesDecoded(0) {} protected: protected: virtual sp<AMessage> onGetFormatAndSeekOptions( virtual sp<AMessage> onGetFormatAndSeekOptions( Loading Loading @@ -146,10 +134,7 @@ struct ImageDecoder : public FrameDecoder { ImageDecoder( ImageDecoder( const AString &componentName, const AString &componentName, const sp<MetaData> &trackMeta, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : const sp<IMediaSource> &source); FrameDecoder(componentName, trackMeta, source), mFrame(NULL), mGridRows(1), mGridCols(1), mTilesDecoded(0), mThumbnail(false) {} protected: protected: virtual sp<AMessage> onGetFormatAndSeekOptions( virtual sp<AMessage> onGetFormatAndSeekOptions( Loading @@ -172,10 +157,11 @@ protected: private: private: VideoFrame *mFrame; VideoFrame *mFrame; int32_t mWidth; int32_t mHeight; int32_t mGridRows; int32_t mGridRows; int32_t mGridCols; int32_t mGridCols; int32_t mTilesDecoded; int32_t mTilesDecoded; bool mThumbnail; }; }; } // namespace android } // namespace android Loading Loading
media/libmediaplayerservice/MetadataRetrieverClient.cpp +0 −4 Original line number Original line Diff line number Diff line Loading @@ -48,7 +48,6 @@ MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid) { { ALOGV("MetadataRetrieverClient constructor pid(%d)", pid); ALOGV("MetadataRetrieverClient constructor pid(%d)", pid); mPid = pid; mPid = pid; mThumbnail = NULL; mAlbumArt = NULL; mAlbumArt = NULL; mRetriever = NULL; mRetriever = NULL; } } Loading Loading @@ -77,7 +76,6 @@ void MetadataRetrieverClient::disconnect() ALOGV("disconnect from pid %d", mPid); ALOGV("disconnect from pid %d", mPid); Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock); mRetriever.clear(); mRetriever.clear(); mThumbnail.clear(); mAlbumArt.clear(); mAlbumArt.clear(); IPCThreadState::self()->flushCommands(); IPCThreadState::self()->flushCommands(); } } Loading Loading @@ -201,7 +199,6 @@ sp<IMemory> MetadataRetrieverClient::getFrameAtTime( (long long)timeUs, option, colorFormat, metaOnly); (long long)timeUs, option, colorFormat, metaOnly); Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock); Mutex::Autolock glock(sLock); Mutex::Autolock glock(sLock); mThumbnail.clear(); if (mRetriever == NULL) { if (mRetriever == NULL) { ALOGE("retriever is not initialized"); ALOGE("retriever is not initialized"); return NULL; return NULL; Loading @@ -220,7 +217,6 @@ sp<IMemory> MetadataRetrieverClient::getImageAtIndex( index, colorFormat, metaOnly, thumbnail); index, colorFormat, metaOnly, thumbnail); Mutex::Autolock lock(mLock); Mutex::Autolock lock(mLock); Mutex::Autolock glock(sLock); Mutex::Autolock glock(sLock); mThumbnail.clear(); if (mRetriever == NULL) { if (mRetriever == NULL) { ALOGE("retriever is not initialized"); ALOGE("retriever is not initialized"); return NULL; return NULL; Loading
media/libmediaplayerservice/MetadataRetrieverClient.h +1 −2 Original line number Original line Diff line number Diff line Loading @@ -73,9 +73,8 @@ private: sp<MediaMetadataRetrieverBase> mRetriever; sp<MediaMetadataRetrieverBase> mRetriever; pid_t mPid; pid_t mPid; // Keep the shared memory copy of album art and capture frame (for thumbnail) // Keep the shared memory copy of album art sp<IMemory> mAlbumArt; sp<IMemory> mAlbumArt; sp<IMemory> mThumbnail; }; }; }; // namespace android }; // namespace android Loading
media/libstagefright/FrameDecoder.cpp +146 −130 Original line number Original line Diff line number Diff line Loading @@ -42,7 +42,6 @@ namespace android { static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec static const int64_t kBufferTimeOutUs = 10000ll; // 10 msec static const size_t kRetryCount = 50; // must be >0 static const size_t kRetryCount = 50; // must be >0 //static sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta, sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta, int32_t width, int32_t height, int32_t dstBpp, bool metaOnly = false) { int32_t width, int32_t height, int32_t dstBpp, bool metaOnly = false) { int32_t rotationAngle; int32_t rotationAngle; Loading Loading @@ -94,7 +93,6 @@ sp<IMemory> allocVideoFrame(const sp<MetaData>& trackMeta, return frameMem; return frameMem; } } //static bool findThumbnailInfo( bool findThumbnailInfo( const sp<MetaData> &trackMeta, int32_t *width, int32_t *height, const sp<MetaData> &trackMeta, int32_t *width, int32_t *height, uint32_t *type = NULL, const void **data = NULL, size_t *size = NULL) { uint32_t *type = NULL, const void **data = NULL, size_t *size = NULL) { Loading @@ -107,30 +105,15 @@ bool findThumbnailInfo( type ?: &dummyType, data ?: &dummyData, size ?: &dummySize); type ?: &dummyType, data ?: &dummyData, size ?: &dummySize); } } //static bool findGridInfo(const sp<MetaData> &trackMeta, sp<IMemory> FrameDecoder::getMetadataOnly( int32_t *tileWidth, int32_t *tileHeight, int32_t *gridRows, int32_t *gridCols) { const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail) { return trackMeta->findInt32(kKeyTileWidth, tileWidth) && (*tileWidth > 0) OMX_COLOR_FORMATTYPE dstFormat; && trackMeta->findInt32(kKeyTileHeight, tileHeight) && (*tileHeight > 0) int32_t dstBpp; && trackMeta->findInt32(kKeyGridRows, gridRows) && (*gridRows > 0) if (!getDstColorFormat( && trackMeta->findInt32(kKeyGridCols, gridCols) && (*gridCols > 0); (android_pixel_format_t)colorFormat, &dstFormat, &dstBpp)) { return NULL; } } int32_t width, height; bool getDstColorFormat( if (thumbnail) { if (!findThumbnailInfo(trackMeta, &width, &height)) { return NULL; } } else { CHECK(trackMeta->findInt32(kKeyWidth, &width)); CHECK(trackMeta->findInt32(kKeyHeight, &height)); } return allocVideoFrame(trackMeta, width, height, dstBpp, true /*metaOnly*/); } //static bool FrameDecoder::getDstColorFormat( android_pixel_format_t colorFormat, android_pixel_format_t colorFormat, OMX_COLOR_FORMATTYPE *dstFormat, OMX_COLOR_FORMATTYPE *dstFormat, int32_t *dstBpp) { int32_t *dstBpp) { Loading Loading @@ -162,46 +145,57 @@ bool FrameDecoder::getDstColorFormat( return false; return false; } } sp<IMemory> FrameDecoder::extractFrame( //static int64_t frameTimeUs, int option, int colorFormat) { sp<IMemory> FrameDecoder::getMetadataOnly( const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail) { OMX_COLOR_FORMATTYPE dstFormat; int32_t dstBpp; if (!getDstColorFormat( if (!getDstColorFormat( (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) { (android_pixel_format_t)colorFormat, &dstFormat, &dstBpp)) { return NULL; return NULL; } } status_t err = extractInternal(frameTimeUs, 1, option); int32_t width, height; if (err != OK) { if (thumbnail) { if (!findThumbnailInfo(trackMeta, &width, &height)) { return NULL; return NULL; } } } else { return mFrames.size() > 0 ? mFrames[0] : NULL; CHECK(trackMeta->findInt32(kKeyWidth, &width)); CHECK(trackMeta->findInt32(kKeyHeight, &height)); } } return allocVideoFrame(trackMeta, width, height, dstBpp, true /*metaOnly*/); status_t FrameDecoder::extractFrames( int64_t frameTimeUs, size_t numFrames, int option, int colorFormat, std::vector<sp<IMemory> >* frames) { if (!getDstColorFormat( (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) { return ERROR_UNSUPPORTED; } } status_t err = extractInternal(frameTimeUs, numFrames, option); FrameDecoder::FrameDecoder( if (err != OK) { const AString &componentName, return err; const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : mComponentName(componentName), mTrackMeta(trackMeta), mSource(source), mDstFormat(OMX_COLOR_Format16bitRGB565), mDstBpp(2), mHaveMoreInputs(true), mFirstSample(true) { } } for (size_t i = 0; i < mFrames.size(); i++) { FrameDecoder::~FrameDecoder() { frames->push_back(mFrames[i]); if (mDecoder != NULL) { mDecoder->release(); mSource->stop(); } } return OK; } } status_t FrameDecoder::extractInternal( status_t FrameDecoder::init( int64_t frameTimeUs, size_t numFrames, int option) { int64_t frameTimeUs, size_t numFrames, int option, int colorFormat) { if (!getDstColorFormat( (android_pixel_format_t)colorFormat, &mDstFormat, &mDstBpp)) { return ERROR_UNSUPPORTED; } MediaSource::ReadOptions options; sp<AMessage> videoFormat = onGetFormatAndSeekOptions( sp<AMessage> videoFormat = onGetFormatAndSeekOptions( frameTimeUs, numFrames, option, &options); frameTimeUs, numFrames, option, &mReadOptions); if (videoFormat == NULL) { if (videoFormat == NULL) { ALOGE("video format or seek mode not supported"); ALOGE("video format or seek mode not supported"); return ERROR_UNSUPPORTED; return ERROR_UNSUPPORTED; Loading @@ -217,7 +211,8 @@ status_t FrameDecoder::extractInternal( return (decoder.get() == NULL) ? NO_MEMORY : err; return (decoder.get() == NULL) ? NO_MEMORY : err; } } err = decoder->configure(videoFormat, NULL /* surface */, NULL /* crypto */, 0 /* flags */); err = decoder->configure( videoFormat, NULL /* surface */, NULL /* crypto */, 0 /* flags */); if (err != OK) { if (err != OK) { ALOGW("configure returned error %d (%s)", err, asString(err)); ALOGW("configure returned error %d (%s)", err, asString(err)); decoder->release(); decoder->release(); Loading @@ -237,43 +232,46 @@ status_t FrameDecoder::extractInternal( decoder->release(); decoder->release(); return err; return err; } } mDecoder = decoder; Vector<sp<MediaCodecBuffer> > inputBuffers; return OK; err = decoder->getInputBuffers(&inputBuffers); } sp<IMemory> FrameDecoder::extractFrame() { status_t err = extractInternal(); if (err != OK) { if (err != OK) { ALOGW("failed to get input buffers: %d (%s)", err, asString(err)); return NULL; decoder->release(); mSource->stop(); return err; } } Vector<sp<MediaCodecBuffer> > outputBuffers; return mFrames.size() > 0 ? mFrames[0] : NULL; err = decoder->getOutputBuffers(&outputBuffers); } status_t FrameDecoder::extractFrames(std::vector<sp<IMemory> >* frames) { status_t err = extractInternal(); if (err != OK) { if (err != OK) { ALOGW("failed to get output buffers: %d (%s)", err, asString(err)); decoder->release(); mSource->stop(); return err; return err; } } sp<AMessage> outputFormat = NULL; for (size_t i = 0; i < mFrames.size(); i++) { bool haveMoreInputs = true; frames->push_back(mFrames[i]); size_t index, offset, size; } int64_t timeUs; return OK; size_t retriesLeft = kRetryCount; } status_t FrameDecoder::extractInternal() { status_t err = OK; bool done = false; bool done = false; bool firstSample = true; size_t retriesLeft = kRetryCount; do { do { size_t inputIndex = -1; size_t index; int64_t ptsUs = 0ll; int64_t ptsUs = 0ll; uint32_t flags = 0; uint32_t flags = 0; sp<MediaCodecBuffer> codecBuffer = NULL; // Queue as many inputs as we possibly can, then block on dequeuing // Queue as many inputs as we possibly can, then block on dequeuing // outputs. After getting each output, come back and queue the inputs // outputs. After getting each output, come back and queue the inputs // again to keep the decoder busy. // again to keep the decoder busy. while (haveMoreInputs) { while (mHaveMoreInputs) { err = decoder->dequeueInputBuffer(&inputIndex, 0); err = mDecoder->dequeueInputBuffer(&index, 0); if (err != OK) { if (err != OK) { ALOGV("Timed out waiting for input"); ALOGV("Timed out waiting for input"); if (retriesLeft) { if (retriesLeft) { Loading @@ -281,16 +279,21 @@ status_t FrameDecoder::extractInternal( } } break; break; } } codecBuffer = inputBuffers[inputIndex]; sp<MediaCodecBuffer> codecBuffer; err = mDecoder->getInputBuffer(index, &codecBuffer); if (err != OK) { ALOGE("failed to get input buffer %zu", index); break; } MediaBufferBase *mediaBuffer = NULL; MediaBufferBase *mediaBuffer = NULL; err = mSource->read(&mediaBuffer, &options); err = mSource->read(&mediaBuffer, &mReadOptions); options.clearSeekTo(); mReadOptions.clearSeekTo(); if (err != OK) { if (err != OK) { ALOGW("Input Error or EOS"); ALOGW("Input Error or EOS"); haveMoreInputs = false; mHaveMoreInputs = false; if (!firstSample && err == ERROR_END_OF_STREAM) { if (!mFirstSample && err == ERROR_END_OF_STREAM) { err = OK; err = OK; } } break; break; Loading @@ -299,7 +302,7 @@ status_t FrameDecoder::extractInternal( if (mediaBuffer->range_length() > codecBuffer->capacity()) { if (mediaBuffer->range_length() > codecBuffer->capacity()) { ALOGE("buffer size (%zu) too large for codec input size (%zu)", ALOGE("buffer size (%zu) too large for codec input size (%zu)", mediaBuffer->range_length(), codecBuffer->capacity()); mediaBuffer->range_length(), codecBuffer->capacity()); haveMoreInputs = false; mHaveMoreInputs = false; err = BAD_VALUE; err = BAD_VALUE; } else { } else { codecBuffer->setRange(0, mediaBuffer->range_length()); codecBuffer->setRange(0, mediaBuffer->range_length()); Loading @@ -309,45 +312,46 @@ status_t FrameDecoder::extractInternal( (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(), (const uint8_t*)mediaBuffer->data() + mediaBuffer->range_offset(), mediaBuffer->range_length()); mediaBuffer->range_length()); onInputReceived(codecBuffer, mediaBuffer->meta_data(), firstSample, &flags); onInputReceived(codecBuffer, mediaBuffer->meta_data(), mFirstSample, &flags); firstSample = false; mFirstSample = false; } } mediaBuffer->release(); mediaBuffer->release(); if (haveMoreInputs && inputIndex < inputBuffers.size()) { if (mHaveMoreInputs) { ALOGV("QueueInput: size=%zu ts=%" PRId64 " us flags=%x", ALOGV("QueueInput: size=%zu ts=%" PRId64 " us flags=%x", codecBuffer->size(), ptsUs, flags); codecBuffer->size(), ptsUs, flags); err = decoder->queueInputBuffer( err = mDecoder->queueInputBuffer( inputIndex, index, codecBuffer->offset(), codecBuffer->offset(), codecBuffer->size(), codecBuffer->size(), ptsUs, ptsUs, flags); flags); if (flags & MediaCodec::BUFFER_FLAG_EOS) { if (flags & MediaCodec::BUFFER_FLAG_EOS) { haveMoreInputs = false; mHaveMoreInputs = false; } } } } } } while (err == OK) { while (err == OK) { size_t offset, size; // wait for a decoded buffer // wait for a decoded buffer err = decoder->dequeueOutputBuffer( err = mDecoder->dequeueOutputBuffer( &index, &index, &offset, &offset, &size, &size, &timeUs, &ptsUs, &flags, &flags, kBufferTimeOutUs); kBufferTimeOutUs); if (err == INFO_FORMAT_CHANGED) { if (err == INFO_FORMAT_CHANGED) { ALOGV("Received format change"); ALOGV("Received format change"); err = decoder->getOutputFormat(&outputFormat); err = mDecoder->getOutputFormat(&mOutputFormat); } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) { ALOGV("Output buffers changed"); ALOGV("Output buffers changed"); err = decoder->getOutputBuffers(&outputBuffers); err = OK; } else { } else { if (err == -EAGAIN /* INFO_TRY_AGAIN_LATER */ && --retriesLeft > 0) { if (err == -EAGAIN /* INFO_TRY_AGAIN_LATER */ && --retriesLeft > 0) { ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft); ALOGV("Timed-out waiting for output.. retries left = %zu", retriesLeft); Loading @@ -355,12 +359,15 @@ status_t FrameDecoder::extractInternal( } else if (err == OK) { } else if (err == OK) { // If we're seeking with CLOSEST option and obtained a valid targetTimeUs // If we're seeking with CLOSEST option and obtained a valid targetTimeUs // from the extractor, decode to the specified frame. Otherwise we're done. // from the extractor, decode to the specified frame. Otherwise we're done. ALOGV("Received an output buffer, timeUs=%lld", (long long)timeUs); ALOGV("Received an output buffer, timeUs=%lld", (long long)ptsUs); sp<MediaCodecBuffer> videoFrameBuffer = outputBuffers.itemAt(index); sp<MediaCodecBuffer> videoFrameBuffer; err = mDecoder->getOutputBuffer(index, &videoFrameBuffer); err = onOutputReceived(videoFrameBuffer, outputFormat, timeUs, &done); if (err != OK) { ALOGE("failed to get output buffer %zu", index); decoder->releaseOutputBuffer(index); break; } err = onOutputReceived(videoFrameBuffer, mOutputFormat, ptsUs, &done); mDecoder->releaseOutputBuffer(index); } else { } else { ALOGW("Received error %d (%s) instead of output", err, asString(err)); ALOGW("Received error %d (%s) instead of output", err, asString(err)); done = true; done = true; Loading @@ -370,9 +377,6 @@ status_t FrameDecoder::extractInternal( } } } while (err == OK && !done); } while (err == OK && !done); mSource->stop(); decoder->release(); if (err != OK) { if (err != OK) { ALOGE("failed to get video frame (err %d)", err); ALOGE("failed to get video frame (err %d)", err); } } Loading @@ -380,6 +384,20 @@ status_t FrameDecoder::extractInternal( return err; return err; } } ////////////////////////////////////////////////////////////////////// VideoFrameDecoder::VideoFrameDecoder( const AString &componentName, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : FrameDecoder(componentName, trackMeta, source), mIsAvcOrHevc(false), mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC), mTargetTimeUs(-1ll), mNumFrames(0), mNumFramesDecoded(0) { } sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions( sp<AMessage> VideoFrameDecoder::onGetFormatAndSeekOptions( int64_t frameTimeUs, size_t numFrames, int seekMode, MediaSource::ReadOptions *options) { int64_t frameTimeUs, size_t numFrames, int seekMode, MediaSource::ReadOptions *options) { mSeekMode = static_cast<MediaSource::ReadOptions::SeekMode>(seekMode); mSeekMode = static_cast<MediaSource::ReadOptions::SeekMode>(seekMode); Loading Loading @@ -511,33 +529,47 @@ status_t VideoFrameDecoder::onOutputReceived( return ERROR_UNSUPPORTED; return ERROR_UNSUPPORTED; } } //////////////////////////////////////////////////////////////////////// ImageDecoder::ImageDecoder( const AString &componentName, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : FrameDecoder(componentName, trackMeta, source), mFrame(NULL), mWidth(0), mHeight(0), mGridRows(1), mGridCols(1), mTilesDecoded(0) { } sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( int64_t frameTimeUs, size_t /*numFrames*/, int64_t frameTimeUs, size_t /*numFrames*/, int /*seekMode*/, MediaSource::ReadOptions *options) { int /*seekMode*/, MediaSource::ReadOptions *options) { sp<MetaData> overrideMeta; sp<MetaData> overrideMeta; mThumbnail = false; if (frameTimeUs < 0) { if (frameTimeUs < 0) { uint32_t type; uint32_t type; const void *data; const void *data; size_t size; size_t size; int32_t thumbWidth, thumbHeight; // if we have a stand-alone thumbnail, set up the override meta, // if we have a stand-alone thumbnail, set up the override meta, // and set seekTo time to -1. // and set seekTo time to -1. if (!findThumbnailInfo(trackMeta(), if (!findThumbnailInfo(trackMeta(), &mWidth, &mHeight, &type, &data, &size)) { &thumbWidth, &thumbHeight, &type, &data, &size)) { ALOGE("Thumbnail not available"); ALOGE("Thumbnail not available"); return NULL; return NULL; } } overrideMeta = new MetaData(*(trackMeta())); overrideMeta = new MetaData(*(trackMeta())); overrideMeta->remove(kKeyDisplayWidth); overrideMeta->remove(kKeyDisplayWidth); overrideMeta->remove(kKeyDisplayHeight); overrideMeta->remove(kKeyDisplayHeight); overrideMeta->setInt32(kKeyWidth, thumbWidth); overrideMeta->setInt32(kKeyWidth, mWidth); overrideMeta->setInt32(kKeyHeight, thumbHeight); overrideMeta->setInt32(kKeyHeight, mHeight); overrideMeta->setData(kKeyHVCC, type, data, size); overrideMeta->setData(kKeyHVCC, type, data, size); options->setSeekTo(-1); options->setSeekTo(-1); mThumbnail = true; } else { } else { CHECK(trackMeta()->findInt32(kKeyWidth, &mWidth)); CHECK(trackMeta()->findInt32(kKeyHeight, &mHeight)); options->setSeekTo(frameTimeUs); options->setSeekTo(frameTimeUs); } } Loading @@ -545,17 +577,10 @@ sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( if (overrideMeta == NULL) { if (overrideMeta == NULL) { // check if we're dealing with a tiled heif // check if we're dealing with a tiled heif int32_t tileWidth, tileHeight, gridRows, gridCols; int32_t tileWidth, tileHeight, gridRows, gridCols; if (trackMeta()->findInt32(kKeyTileWidth, &tileWidth) && tileWidth > 0 if (findGridInfo(trackMeta(), &tileWidth, &tileHeight, &gridRows, &gridCols)) { && trackMeta()->findInt32(kKeyTileHeight, &tileHeight) && tileHeight > 0 if (mWidth <= tileWidth * gridCols && mHeight <= tileHeight * gridRows) { && trackMeta()->findInt32(kKeyGridRows, &gridRows) && gridRows > 0 && trackMeta()->findInt32(kKeyGridCols, &gridCols) && gridCols > 0) { int32_t width, height; CHECK(trackMeta()->findInt32(kKeyWidth, &width)); CHECK(trackMeta()->findInt32(kKeyHeight, &height)); if (width <= tileWidth * gridCols && height <= tileHeight * gridRows) { ALOGV("grid: %dx%d, tile size: %dx%d, picture size: %dx%d", ALOGV("grid: %dx%d, tile size: %dx%d, picture size: %dx%d", gridCols, gridRows, tileWidth, tileHeight, width, height); gridCols, gridRows, tileWidth, tileHeight, mWidth, mHeight); overrideMeta = new MetaData(*(trackMeta())); overrideMeta = new MetaData(*(trackMeta())); overrideMeta->setInt32(kKeyWidth, tileWidth); overrideMeta->setInt32(kKeyWidth, tileWidth); Loading @@ -563,8 +588,8 @@ sp<AMessage> ImageDecoder::onGetFormatAndSeekOptions( mGridCols = gridCols; mGridCols = gridCols; mGridRows = gridRows; mGridRows = gridRows; } else { } else { ALOGE("bad grid: %dx%d, tile size: %dx%d, picture size: %dx%d", ALOGE("ignore bad grid: %dx%d, tile size: %dx%d, picture size: %dx%d", gridCols, gridRows, tileWidth, tileHeight, width, height); gridCols, gridRows, tileWidth, tileHeight, mWidth, mHeight); } } } } if (overrideMeta == NULL) { if (overrideMeta == NULL) { Loading Loading @@ -600,17 +625,8 @@ status_t ImageDecoder::onOutputReceived( CHECK(outputFormat->findInt32("width", &width)); CHECK(outputFormat->findInt32("width", &width)); CHECK(outputFormat->findInt32("height", &height)); CHECK(outputFormat->findInt32("height", &height)); int32_t imageWidth, imageHeight; if (mThumbnail) { CHECK(trackMeta()->findInt32(kKeyThumbnailWidth, &imageWidth)); CHECK(trackMeta()->findInt32(kKeyThumbnailHeight, &imageHeight)); } else { CHECK(trackMeta()->findInt32(kKeyWidth, &imageWidth)); CHECK(trackMeta()->findInt32(kKeyHeight, &imageHeight)); } if (mFrame == NULL) { if (mFrame == NULL) { sp<IMemory> frameMem = allocVideoFrame(trackMeta(), imageWidth, imageHeight, dstBpp()); sp<IMemory> frameMem = allocVideoFrame(trackMeta(), mWidth, mHeight, dstBpp()); mFrame = static_cast<VideoFrame*>(frameMem->pointer()); mFrame = static_cast<VideoFrame*>(frameMem->pointer()); addFrame(frameMem); addFrame(frameMem); Loading Loading @@ -638,12 +654,12 @@ status_t ImageDecoder::onOutputReceived( // apply crop on bottom-right // apply crop on bottom-right // TODO: need to move this into the color converter itself. // TODO: need to move this into the color converter itself. if (dstRight >= imageWidth) { if (dstRight >= mWidth) { crop_right = imageWidth - dstLeft - 1; crop_right = mWidth - dstLeft - 1; dstRight = dstLeft + crop_right; dstRight = dstLeft + crop_right; } } if (dstBottom >= imageHeight) { if (dstBottom >= mHeight) { crop_bottom = imageHeight - dstTop - 1; crop_bottom = mHeight - dstTop - 1; dstBottom = dstTop + crop_bottom; dstBottom = dstTop + crop_bottom; } } Loading
media/libstagefright/StagefrightMetadataRetriever.cpp +17 −14 Original line number Original line Diff line number Diff line Loading @@ -193,12 +193,14 @@ sp<IMemory> StagefrightMetadataRetriever::getImageAtIndex( for (size_t i = 0; i < matchingCodecs.size(); ++i) { for (size_t i = 0; i < matchingCodecs.size(); ++i) { const AString &componentName = matchingCodecs[i]; const AString &componentName = matchingCodecs[i]; ImageDecoder decoder(componentName, trackMeta, source); ImageDecoder decoder(componentName, trackMeta, source); sp<IMemory> frame = decoder.extractFrame( int64_t frameTimeUs = thumbnail ? -1 : 0; thumbnail ? -1 : 0 /*frameTimeUs*/, 0 /*seekMode*/, colorFormat); if (decoder.init(frameTimeUs, 1 /*numFrames*/, 0 /*option*/, colorFormat) == OK) { sp<IMemory> frame = decoder.extractFrame(); if (frame != NULL) { if (frame != NULL) { return frame; return frame; } } } ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str()); ALOGV("%s failed to extract thumbnail, trying next decoder.", componentName.c_str()); } } Loading Loading @@ -307,18 +309,19 @@ status_t StagefrightMetadataRetriever::getFrameInternal( for (size_t i = 0; i < matchingCodecs.size(); ++i) { for (size_t i = 0; i < matchingCodecs.size(); ++i) { const AString &componentName = matchingCodecs[i]; const AString &componentName = matchingCodecs[i]; VideoFrameDecoder decoder(componentName, trackMeta, source); VideoFrameDecoder decoder(componentName, trackMeta, source); if (decoder.init(timeUs, numFrames, option, colorFormat) == OK) { if (outFrame != NULL) { if (outFrame != NULL) { *outFrame = decoder.extractFrame(timeUs, option, colorFormat); *outFrame = decoder.extractFrame(); if (*outFrame != NULL) { if (*outFrame != NULL) { return OK; return OK; } } } else if (outFrames != NULL) { } else if (outFrames != NULL) { status_t err = decoder.extractFrames( status_t err = decoder.extractFrames(outFrames); timeUs, numFrames, option, colorFormat, outFrames); if (err == OK) { if (err == OK) { return OK; return OK; } } } } } ALOGV("%s failed to extract frame, trying next decoder.", componentName.c_str()); ALOGV("%s failed to extract frame, trying next decoder.", componentName.c_str()); } } Loading
media/libstagefright/include/FrameDecoder.h +18 −32 Original line number Original line Diff line number Diff line Loading @@ -32,32 +32,26 @@ struct AMessage; class MediaCodecBuffer; class MediaCodecBuffer; class IMediaSource; class IMediaSource; class VideoFrame; class VideoFrame; struct MediaCodec; struct FrameDecoder { struct FrameDecoder { FrameDecoder( FrameDecoder( const AString &componentName, const AString &componentName, const sp<MetaData> &trackMeta, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : const sp<IMediaSource> &source); mComponentName(componentName), mTrackMeta(trackMeta), mSource(source), mDstFormat(OMX_COLOR_Format16bitRGB565), mDstBpp(2) {} sp<IMemory> extractFrame(int64_t frameTimeUs, int option, int colorFormat); status_t init( int64_t frameTimeUs, size_t numFrames, int option, int colorFormat); status_t extractFrames( sp<IMemory> extractFrame(); int64_t frameTimeUs, size_t numFrames, status_t extractFrames(std::vector<sp<IMemory> >* frames); int option, int colorFormat, std::vector<sp<IMemory> >* frames); static sp<IMemory> getMetadataOnly( static sp<IMemory> getMetadataOnly( const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail = false); const sp<MetaData> &trackMeta, int colorFormat, bool thumbnail = false); protected: protected: virtual ~FrameDecoder() {} virtual ~FrameDecoder(); virtual sp<AMessage> onGetFormatAndSeekOptions( virtual sp<AMessage> onGetFormatAndSeekOptions( int64_t frameTimeUs, int64_t frameTimeUs, Loading Loading @@ -92,13 +86,13 @@ private: OMX_COLOR_FORMATTYPE mDstFormat; OMX_COLOR_FORMATTYPE mDstFormat; int32_t mDstBpp; int32_t mDstBpp; std::vector<sp<IMemory> > mFrames; std::vector<sp<IMemory> > mFrames; MediaSource::ReadOptions mReadOptions; sp<MediaCodec> mDecoder; sp<AMessage> mOutputFormat; bool mHaveMoreInputs; bool mFirstSample; static bool getDstColorFormat( status_t extractInternal(); android_pixel_format_t colorFormat, OMX_COLOR_FORMATTYPE *dstFormat, int32_t *dstBpp); status_t extractInternal(int64_t frameTimeUs, size_t numFrames, int option); DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder); DISALLOW_EVIL_CONSTRUCTORS(FrameDecoder); }; }; Loading @@ -107,13 +101,7 @@ struct VideoFrameDecoder : public FrameDecoder { VideoFrameDecoder( VideoFrameDecoder( const AString &componentName, const AString &componentName, const sp<MetaData> &trackMeta, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : const sp<IMediaSource> &source); FrameDecoder(componentName, trackMeta, source), mIsAvcOrHevc(false), mSeekMode(MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC), mTargetTimeUs(-1ll), mNumFrames(0), mNumFramesDecoded(0) {} protected: protected: virtual sp<AMessage> onGetFormatAndSeekOptions( virtual sp<AMessage> onGetFormatAndSeekOptions( Loading Loading @@ -146,10 +134,7 @@ struct ImageDecoder : public FrameDecoder { ImageDecoder( ImageDecoder( const AString &componentName, const AString &componentName, const sp<MetaData> &trackMeta, const sp<MetaData> &trackMeta, const sp<IMediaSource> &source) : const sp<IMediaSource> &source); FrameDecoder(componentName, trackMeta, source), mFrame(NULL), mGridRows(1), mGridCols(1), mTilesDecoded(0), mThumbnail(false) {} protected: protected: virtual sp<AMessage> onGetFormatAndSeekOptions( virtual sp<AMessage> onGetFormatAndSeekOptions( Loading @@ -172,10 +157,11 @@ protected: private: private: VideoFrame *mFrame; VideoFrame *mFrame; int32_t mWidth; int32_t mHeight; int32_t mGridRows; int32_t mGridRows; int32_t mGridCols; int32_t mGridCols; int32_t mTilesDecoded; int32_t mTilesDecoded; bool mThumbnail; }; }; } // namespace android } // namespace android Loading