Loading media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <media/MediaSampleReaderNDK.h> #include <algorithm> #include <cmath> #include <vector> namespace android { Loading Loading @@ -189,6 +190,78 @@ media_status_t MediaSampleReaderNDK::positionExtractorForTrack_l(int trackIndex) return AMEDIA_OK; } media_status_t MediaSampleReaderNDK::getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) { std::scoped_lock lock(mExtractorMutex); media_status_t status = AMEDIA_OK; if (trackIndex < 0 || trackIndex >= mTrackCount) { LOG(ERROR) << "Invalid trackIndex " << trackIndex << " for trackCount " << mTrackCount; return AMEDIA_ERROR_INVALID_PARAMETER; } else if (bitrate == nullptr) { LOG(ERROR) << "bitrate pointer is NULL."; return AMEDIA_ERROR_INVALID_PARAMETER; } // Rewind the extractor and sample from the beginning of the file. if (mExtractorSampleIndex > 0) { status = AMediaExtractor_seekTo(mExtractor, 0, AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC); if (status != AMEDIA_OK) { LOG(ERROR) << "Unable to reset extractor: " << status; return status; } mExtractorTrackIndex = AMediaExtractor_getSampleTrackIndex(mExtractor); mExtractorSampleIndex = 0; } // Sample the track. static constexpr int64_t kSamplingDurationUs = 10 * 1000 * 1000; // 10 seconds size_t lastSampleSize = 0; size_t totalSampleSize = 0; int64_t firstSampleTimeUs = 0; int64_t lastSampleTimeUs = 0; do { if (mExtractorTrackIndex == trackIndex) { lastSampleTimeUs = AMediaExtractor_getSampleTime(mExtractor); if (totalSampleSize == 0) { firstSampleTimeUs = lastSampleTimeUs; } lastSampleSize = AMediaExtractor_getSampleSize(mExtractor); totalSampleSize += lastSampleSize; } } while ((lastSampleTimeUs - firstSampleTimeUs) < kSamplingDurationUs && advanceExtractor_l()); int64_t durationUs = 0; const int64_t sampledDurationUs = lastSampleTimeUs - firstSampleTimeUs; if (sampledDurationUs < kSamplingDurationUs) { // Track is shorter than the sampling duration so use the full track duration to get better // accuracy (i.e. don't skip the last sample). AMediaFormat* trackFormat = getTrackFormat(trackIndex); if (!AMediaFormat_getInt64(trackFormat, AMEDIAFORMAT_KEY_DURATION, &durationUs)) { durationUs = 0; } AMediaFormat_delete(trackFormat); } if (durationUs == 0) { // The sampled duration does not account for the last sample's duration so its size should // not be included either. totalSampleSize -= lastSampleSize; durationUs = sampledDurationUs; } if (totalSampleSize == 0 || durationUs <= 0) { LOG(ERROR) << "Unable to estimate track bitrate"; return AMEDIA_ERROR_MALFORMED; } *bitrate = roundf((float)totalSampleSize * 8 * 1000000 / durationUs); return AMEDIA_OK; } media_status_t MediaSampleReaderNDK::getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) { std::scoped_lock lock(mExtractorMutex); Loading media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -45,9 +45,8 @@ media_status_t MediaTrackTranscoder::configure( mMediaSampleReader = mediaSampleReader; mTrackIndex = trackIndex; mSourceFormat = std::shared_ptr<AMediaFormat>(mMediaSampleReader->getTrackFormat(mTrackIndex), std::bind(AMediaFormat_delete, std::placeholders::_1)); mSourceFormat = std::shared_ptr<AMediaFormat>(mMediaSampleReader->getTrackFormat(mTrackIndex), &AMediaFormat_delete); if (mSourceFormat == nullptr) { LOG(ERROR) << "Unable to get format for track #" << mTrackIndex; return AMEDIA_ERROR_MALFORMED; Loading media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,8 @@ VideoTrackTranscoder::~VideoTrackTranscoder() { // Creates and configures the codecs. media_status_t VideoTrackTranscoder::configureDestinationFormat( const std::shared_ptr<AMediaFormat>& destinationFormat) { static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000; media_status_t status = AMEDIA_OK; if (destinationFormat == nullptr) { Loading @@ -177,6 +179,18 @@ media_status_t VideoTrackTranscoder::configureDestinationFormat( return AMEDIA_ERROR_INVALID_PARAMETER; } int32_t bitrate; if (!AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate)) { status = mMediaSampleReader->getEstimatedBitrateForTrack(mTrackIndex, &bitrate); if (status != AMEDIA_OK) { LOG(ERROR) << "Unable to estimate bitrate. Using default " << kDefaultBitrateMbps; bitrate = kDefaultBitrateMbps; } LOG(INFO) << "Configuring bitrate " << bitrate; AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_BIT_RATE, bitrate); } float tmp; if (!AMediaFormat_getFloat(encoderFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, &tmp)) { AMediaFormat_setFloat(encoderFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, Loading media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h +10 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,16 @@ public: */ virtual AMediaFormat* getTrackFormat(int trackIndex) = 0; /** * Estimates the bitrate of a source track by sampling sample sizes. The bitrate is returned in * megabits per second (Mbps). This method will fail if the track only contains a single sample * and does not have an associated duration. * @param trackIndex The source track index. * @param bitrate Output param for the bitrate. * @return AMEDIA_OK on success. */ virtual media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate); /** * Returns the sample information for the current sample in the specified track. * @param trackIndex The track index (zero-based). Loading media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h +1 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ public: AMediaFormat* getFileFormat() override; size_t getTrackCount() const override; AMediaFormat* getTrackFormat(int trackIndex) override; media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) override; media_status_t getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) override; media_status_t readSampleDataForTrack(int trackIndex, uint8_t* buffer, size_t bufferSize) override; Loading Loading
media/libmediatranscoding/transcoder/MediaSampleReaderNDK.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <media/MediaSampleReaderNDK.h> #include <algorithm> #include <cmath> #include <vector> namespace android { Loading Loading @@ -189,6 +190,78 @@ media_status_t MediaSampleReaderNDK::positionExtractorForTrack_l(int trackIndex) return AMEDIA_OK; } media_status_t MediaSampleReaderNDK::getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) { std::scoped_lock lock(mExtractorMutex); media_status_t status = AMEDIA_OK; if (trackIndex < 0 || trackIndex >= mTrackCount) { LOG(ERROR) << "Invalid trackIndex " << trackIndex << " for trackCount " << mTrackCount; return AMEDIA_ERROR_INVALID_PARAMETER; } else if (bitrate == nullptr) { LOG(ERROR) << "bitrate pointer is NULL."; return AMEDIA_ERROR_INVALID_PARAMETER; } // Rewind the extractor and sample from the beginning of the file. if (mExtractorSampleIndex > 0) { status = AMediaExtractor_seekTo(mExtractor, 0, AMEDIAEXTRACTOR_SEEK_PREVIOUS_SYNC); if (status != AMEDIA_OK) { LOG(ERROR) << "Unable to reset extractor: " << status; return status; } mExtractorTrackIndex = AMediaExtractor_getSampleTrackIndex(mExtractor); mExtractorSampleIndex = 0; } // Sample the track. static constexpr int64_t kSamplingDurationUs = 10 * 1000 * 1000; // 10 seconds size_t lastSampleSize = 0; size_t totalSampleSize = 0; int64_t firstSampleTimeUs = 0; int64_t lastSampleTimeUs = 0; do { if (mExtractorTrackIndex == trackIndex) { lastSampleTimeUs = AMediaExtractor_getSampleTime(mExtractor); if (totalSampleSize == 0) { firstSampleTimeUs = lastSampleTimeUs; } lastSampleSize = AMediaExtractor_getSampleSize(mExtractor); totalSampleSize += lastSampleSize; } } while ((lastSampleTimeUs - firstSampleTimeUs) < kSamplingDurationUs && advanceExtractor_l()); int64_t durationUs = 0; const int64_t sampledDurationUs = lastSampleTimeUs - firstSampleTimeUs; if (sampledDurationUs < kSamplingDurationUs) { // Track is shorter than the sampling duration so use the full track duration to get better // accuracy (i.e. don't skip the last sample). AMediaFormat* trackFormat = getTrackFormat(trackIndex); if (!AMediaFormat_getInt64(trackFormat, AMEDIAFORMAT_KEY_DURATION, &durationUs)) { durationUs = 0; } AMediaFormat_delete(trackFormat); } if (durationUs == 0) { // The sampled duration does not account for the last sample's duration so its size should // not be included either. totalSampleSize -= lastSampleSize; durationUs = sampledDurationUs; } if (totalSampleSize == 0 || durationUs <= 0) { LOG(ERROR) << "Unable to estimate track bitrate"; return AMEDIA_ERROR_MALFORMED; } *bitrate = roundf((float)totalSampleSize * 8 * 1000000 / durationUs); return AMEDIA_OK; } media_status_t MediaSampleReaderNDK::getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) { std::scoped_lock lock(mExtractorMutex); Loading
media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp +2 −3 Original line number Diff line number Diff line Loading @@ -45,9 +45,8 @@ media_status_t MediaTrackTranscoder::configure( mMediaSampleReader = mediaSampleReader; mTrackIndex = trackIndex; mSourceFormat = std::shared_ptr<AMediaFormat>(mMediaSampleReader->getTrackFormat(mTrackIndex), std::bind(AMediaFormat_delete, std::placeholders::_1)); mSourceFormat = std::shared_ptr<AMediaFormat>(mMediaSampleReader->getTrackFormat(mTrackIndex), &AMediaFormat_delete); if (mSourceFormat == nullptr) { LOG(ERROR) << "Unable to get format for track #" << mTrackIndex; return AMEDIA_ERROR_MALFORMED; Loading
media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -164,6 +164,8 @@ VideoTrackTranscoder::~VideoTrackTranscoder() { // Creates and configures the codecs. media_status_t VideoTrackTranscoder::configureDestinationFormat( const std::shared_ptr<AMediaFormat>& destinationFormat) { static constexpr int32_t kDefaultBitrateMbps = 10 * 1000 * 1000; media_status_t status = AMEDIA_OK; if (destinationFormat == nullptr) { Loading @@ -177,6 +179,18 @@ media_status_t VideoTrackTranscoder::configureDestinationFormat( return AMEDIA_ERROR_INVALID_PARAMETER; } int32_t bitrate; if (!AMediaFormat_getInt32(encoderFormat, AMEDIAFORMAT_KEY_BIT_RATE, &bitrate)) { status = mMediaSampleReader->getEstimatedBitrateForTrack(mTrackIndex, &bitrate); if (status != AMEDIA_OK) { LOG(ERROR) << "Unable to estimate bitrate. Using default " << kDefaultBitrateMbps; bitrate = kDefaultBitrateMbps; } LOG(INFO) << "Configuring bitrate " << bitrate; AMediaFormat_setInt32(encoderFormat, AMEDIAFORMAT_KEY_BIT_RATE, bitrate); } float tmp; if (!AMediaFormat_getFloat(encoderFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, &tmp)) { AMediaFormat_setFloat(encoderFormat, AMEDIAFORMAT_KEY_I_FRAME_INTERVAL, Loading
media/libmediatranscoding/transcoder/include/media/MediaSampleReader.h +10 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,16 @@ public: */ virtual AMediaFormat* getTrackFormat(int trackIndex) = 0; /** * Estimates the bitrate of a source track by sampling sample sizes. The bitrate is returned in * megabits per second (Mbps). This method will fail if the track only contains a single sample * and does not have an associated duration. * @param trackIndex The source track index. * @param bitrate Output param for the bitrate. * @return AMEDIA_OK on success. */ virtual media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate); /** * Returns the sample information for the current sample in the specified track. * @param trackIndex The track index (zero-based). Loading
media/libmediatranscoding/transcoder/include/media/MediaSampleReaderNDK.h +1 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ public: AMediaFormat* getFileFormat() override; size_t getTrackCount() const override; AMediaFormat* getTrackFormat(int trackIndex) override; media_status_t getEstimatedBitrateForTrack(int trackIndex, int32_t* bitrate) override; media_status_t getSampleInfoForTrack(int trackIndex, MediaSampleInfo* info) override; media_status_t readSampleDataForTrack(int trackIndex, uint8_t* buffer, size_t bufferSize) override; Loading