Loading media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,12 @@ bool MediaTrackTranscoder::stop() { return false; } void MediaTrackTranscoder::notifyTrackFormatAvailable() { if (auto callbacks = mTranscoderCallback.lock()) { callbacks->onTrackFormatAvailable(this); } } std::shared_ptr<MediaSampleQueue> MediaTrackTranscoder::getOutputQueue() const { return mOutputQueue; } Loading media/libmediatranscoding/transcoder/MediaTranscoder.cpp +31 −17 Original line number Diff line number Diff line Loading @@ -100,6 +100,36 @@ void MediaTranscoder::sendCallback(media_status_t status) { } } void MediaTranscoder::onTrackFormatAvailable(const MediaTrackTranscoder* transcoder) { LOG(INFO) << "TrackTranscoder " << transcoder << " format available."; std::scoped_lock lock{mTracksAddedMutex}; // Ignore duplicate format change. if (mTracksAdded.count(transcoder) > 0) { return; } // Add track to the writer. const bool ok = mSampleWriter->addTrack(transcoder->getOutputQueue(), transcoder->getOutputFormat()); if (!ok) { LOG(ERROR) << "Unable to add track to sample writer."; sendCallback(AMEDIA_ERROR_UNKNOWN); return; } mTracksAdded.insert(transcoder); if (mTracksAdded.size() == mTrackTranscoders.size()) { LOG(INFO) << "Starting sample writer."; bool started = mSampleWriter->start(); if (!started) { LOG(ERROR) << "Unable to start sample writer."; sendCallback(AMEDIA_ERROR_UNKNOWN); } } } void MediaTranscoder::onTrackFinished(const MediaTrackTranscoder* transcoder) { LOG(DEBUG) << "TrackTranscoder " << transcoder << " finished"; } Loading Loading @@ -267,25 +297,9 @@ media_status_t MediaTranscoder::start() { return AMEDIA_ERROR_INVALID_OPERATION; } // Add tracks to the writer. for (auto& transcoder : mTrackTranscoders) { const bool ok = mSampleWriter->addTrack(transcoder->getOutputQueue(), transcoder->getOutputFormat()); if (!ok) { LOG(ERROR) << "Unable to add track to sample writer."; return AMEDIA_ERROR_UNKNOWN; } } bool started = mSampleWriter->start(); if (!started) { LOG(ERROR) << "Unable to start sample writer."; return AMEDIA_ERROR_UNKNOWN; } // Start transcoders for (auto& transcoder : mTrackTranscoders) { started = transcoder->start(); bool started = transcoder->start(); if (!started) { LOG(ERROR) << "Unable to start track transcoder."; cancel(); Loading media/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ media_status_t PassthroughTrackTranscoder::runTranscodeLoop() { MediaSampleInfo info; std::shared_ptr<MediaSample> sample; // Notify the track format as soon as we start. It's same as the source format. notifyTrackFormatAvailable(); MediaSample::OnSampleReleasedCallback bufferReleaseCallback = [bufferPool = mBufferPool](MediaSample* sample) { bufferPool->returnBuffer(const_cast<uint8_t*>(sample->buffer)); Loading media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp +55 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,10 @@ struct AsyncCodecCallbackDispatch { VideoTrackTranscoder* transcoder = static_cast<VideoTrackTranscoder*>(userdata); const char* kCodecName = (codec == transcoder->mDecoder ? "Decoder" : "Encoder"); LOG(DEBUG) << kCodecName << " format changed: " << AMediaFormat_toString(format); if (codec == transcoder->mEncoder.get()) { transcoder->mCodecMessageQueue.push( [transcoder, format] { transcoder->updateTrackFormat(format); }); } } static void onAsyncError(AMediaCodec* codec, void* userdata, media_status_t error, Loading Loading @@ -311,6 +315,56 @@ void VideoTrackTranscoder::dequeueOutputSample(int32_t bufferIndex, } } void VideoTrackTranscoder::updateTrackFormat(AMediaFormat* outputFormat) { if (mActualOutputFormat != nullptr) { LOG(WARNING) << "Ignoring duplicate format change."; return; } AMediaFormat* formatCopy = AMediaFormat_new(); if (!formatCopy || AMediaFormat_copy(formatCopy, outputFormat) != AMEDIA_OK) { LOG(ERROR) << "Unable to copy outputFormat"; AMediaFormat_delete(formatCopy); mStatus = AMEDIA_ERROR_INVALID_PARAMETER; return; } // Generate the actual track format for muxer based on the encoder output format, // since many vital information comes in the encoder format (eg. CSD). // Transfer necessary fields from the user-configured track format (derived from // source track format and user transcoding request) where needed. // Transfer SAR settings: // If mDestinationFormat has SAR set, it means the original source has SAR specified // at container level. This is supposed to override any SAR settings in the bitstream, // thus should always be transferred to the container of the transcoded file. int32_t sarWidth, sarHeight; if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_WIDTH, &sarWidth) && (sarWidth > 0) && AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_HEIGHT, &sarHeight) && (sarHeight > 0)) { AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth); AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight); } // Transfer DAR settings. int32_t displayWidth, displayHeight; if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_WIDTH, &displayWidth) && (displayWidth > 0) && AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, &displayHeight) && (displayHeight > 0)) { AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_WIDTH, displayWidth); AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, displayHeight); } // TODO: transfer other fields as required. mActualOutputFormat = std::shared_ptr<AMediaFormat>(formatCopy, &AMediaFormat_delete); notifyTrackFormatAvailable(); } media_status_t VideoTrackTranscoder::runTranscodeLoop() { media_status_t status = AMEDIA_OK; Loading Loading @@ -350,7 +404,7 @@ void VideoTrackTranscoder::abortTranscodeLoop() { } std::shared_ptr<AMediaFormat> VideoTrackTranscoder::getOutputFormat() const { return mDestinationFormat; return mActualOutputFormat; } } // namespace android media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h +3 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,9 @@ protected: : mOutputQueue(std::make_shared<MediaSampleQueue>()), mTranscoderCallback(transcoderCallback){}; // Called by subclasses when the actual track format becomes available. void notifyTrackFormatAvailable(); // configureDestinationFormat needs to be implemented by subclasses, and gets called on an // external thread before start. virtual media_status_t configureDestinationFormat( Loading Loading
media/libmediatranscoding/transcoder/MediaTrackTranscoder.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,12 @@ bool MediaTrackTranscoder::stop() { return false; } void MediaTrackTranscoder::notifyTrackFormatAvailable() { if (auto callbacks = mTranscoderCallback.lock()) { callbacks->onTrackFormatAvailable(this); } } std::shared_ptr<MediaSampleQueue> MediaTrackTranscoder::getOutputQueue() const { return mOutputQueue; } Loading
media/libmediatranscoding/transcoder/MediaTranscoder.cpp +31 −17 Original line number Diff line number Diff line Loading @@ -100,6 +100,36 @@ void MediaTranscoder::sendCallback(media_status_t status) { } } void MediaTranscoder::onTrackFormatAvailable(const MediaTrackTranscoder* transcoder) { LOG(INFO) << "TrackTranscoder " << transcoder << " format available."; std::scoped_lock lock{mTracksAddedMutex}; // Ignore duplicate format change. if (mTracksAdded.count(transcoder) > 0) { return; } // Add track to the writer. const bool ok = mSampleWriter->addTrack(transcoder->getOutputQueue(), transcoder->getOutputFormat()); if (!ok) { LOG(ERROR) << "Unable to add track to sample writer."; sendCallback(AMEDIA_ERROR_UNKNOWN); return; } mTracksAdded.insert(transcoder); if (mTracksAdded.size() == mTrackTranscoders.size()) { LOG(INFO) << "Starting sample writer."; bool started = mSampleWriter->start(); if (!started) { LOG(ERROR) << "Unable to start sample writer."; sendCallback(AMEDIA_ERROR_UNKNOWN); } } } void MediaTranscoder::onTrackFinished(const MediaTrackTranscoder* transcoder) { LOG(DEBUG) << "TrackTranscoder " << transcoder << " finished"; } Loading Loading @@ -267,25 +297,9 @@ media_status_t MediaTranscoder::start() { return AMEDIA_ERROR_INVALID_OPERATION; } // Add tracks to the writer. for (auto& transcoder : mTrackTranscoders) { const bool ok = mSampleWriter->addTrack(transcoder->getOutputQueue(), transcoder->getOutputFormat()); if (!ok) { LOG(ERROR) << "Unable to add track to sample writer."; return AMEDIA_ERROR_UNKNOWN; } } bool started = mSampleWriter->start(); if (!started) { LOG(ERROR) << "Unable to start sample writer."; return AMEDIA_ERROR_UNKNOWN; } // Start transcoders for (auto& transcoder : mTrackTranscoders) { started = transcoder->start(); bool started = transcoder->start(); if (!started) { LOG(ERROR) << "Unable to start track transcoder."; cancel(); Loading
media/libmediatranscoding/transcoder/PassthroughTrackTranscoder.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,9 @@ media_status_t PassthroughTrackTranscoder::runTranscodeLoop() { MediaSampleInfo info; std::shared_ptr<MediaSample> sample; // Notify the track format as soon as we start. It's same as the source format. notifyTrackFormatAvailable(); MediaSample::OnSampleReleasedCallback bufferReleaseCallback = [bufferPool = mBufferPool](MediaSample* sample) { bufferPool->returnBuffer(const_cast<uint8_t*>(sample->buffer)); Loading
media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp +55 −1 Original line number Diff line number Diff line Loading @@ -86,6 +86,10 @@ struct AsyncCodecCallbackDispatch { VideoTrackTranscoder* transcoder = static_cast<VideoTrackTranscoder*>(userdata); const char* kCodecName = (codec == transcoder->mDecoder ? "Decoder" : "Encoder"); LOG(DEBUG) << kCodecName << " format changed: " << AMediaFormat_toString(format); if (codec == transcoder->mEncoder.get()) { transcoder->mCodecMessageQueue.push( [transcoder, format] { transcoder->updateTrackFormat(format); }); } } static void onAsyncError(AMediaCodec* codec, void* userdata, media_status_t error, Loading Loading @@ -311,6 +315,56 @@ void VideoTrackTranscoder::dequeueOutputSample(int32_t bufferIndex, } } void VideoTrackTranscoder::updateTrackFormat(AMediaFormat* outputFormat) { if (mActualOutputFormat != nullptr) { LOG(WARNING) << "Ignoring duplicate format change."; return; } AMediaFormat* formatCopy = AMediaFormat_new(); if (!formatCopy || AMediaFormat_copy(formatCopy, outputFormat) != AMEDIA_OK) { LOG(ERROR) << "Unable to copy outputFormat"; AMediaFormat_delete(formatCopy); mStatus = AMEDIA_ERROR_INVALID_PARAMETER; return; } // Generate the actual track format for muxer based on the encoder output format, // since many vital information comes in the encoder format (eg. CSD). // Transfer necessary fields from the user-configured track format (derived from // source track format and user transcoding request) where needed. // Transfer SAR settings: // If mDestinationFormat has SAR set, it means the original source has SAR specified // at container level. This is supposed to override any SAR settings in the bitstream, // thus should always be transferred to the container of the transcoded file. int32_t sarWidth, sarHeight; if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_WIDTH, &sarWidth) && (sarWidth > 0) && AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_SAR_HEIGHT, &sarHeight) && (sarHeight > 0)) { AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_WIDTH, sarWidth); AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_SAR_HEIGHT, sarHeight); } // Transfer DAR settings. int32_t displayWidth, displayHeight; if (AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_WIDTH, &displayWidth) && (displayWidth > 0) && AMediaFormat_getInt32(mDestinationFormat.get(), AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, &displayHeight) && (displayHeight > 0)) { AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_WIDTH, displayWidth); AMediaFormat_setInt32(formatCopy, AMEDIAFORMAT_KEY_DISPLAY_HEIGHT, displayHeight); } // TODO: transfer other fields as required. mActualOutputFormat = std::shared_ptr<AMediaFormat>(formatCopy, &AMediaFormat_delete); notifyTrackFormatAvailable(); } media_status_t VideoTrackTranscoder::runTranscodeLoop() { media_status_t status = AMEDIA_OK; Loading Loading @@ -350,7 +404,7 @@ void VideoTrackTranscoder::abortTranscodeLoop() { } std::shared_ptr<AMediaFormat> VideoTrackTranscoder::getOutputFormat() const { return mDestinationFormat; return mActualOutputFormat; } } // namespace android
media/libmediatranscoding/transcoder/include/media/MediaTrackTranscoder.h +3 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,9 @@ protected: : mOutputQueue(std::make_shared<MediaSampleQueue>()), mTranscoderCallback(transcoderCallback){}; // Called by subclasses when the actual track format becomes available. void notifyTrackFormatAvailable(); // configureDestinationFormat needs to be implemented by subclasses, and gets called on an // external thread before start. virtual media_status_t configureDestinationFormat( Loading