Merge "Transcoder: Don't preserve profile/level when switching codec." into sc-dev
diff --git a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
index 74ddce4..413f049 100644
--- a/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/MediaTranscoder.cpp
@@ -29,24 +29,37 @@
namespace android {
-static AMediaFormat* mergeMediaFormats(AMediaFormat* base, AMediaFormat* overlay) {
- if (base == nullptr || overlay == nullptr) {
+static std::shared_ptr<AMediaFormat> createVideoTrackFormat(AMediaFormat* srcFormat,
+ AMediaFormat* options) {
+ if (srcFormat == nullptr || options == nullptr) {
LOG(ERROR) << "Cannot merge null formats";
return nullptr;
}
- AMediaFormat* format = AMediaFormat_new();
- if (AMediaFormat_copy(format, base) != AMEDIA_OK) {
- AMediaFormat_delete(format);
- return nullptr;
+ // ------- Define parameters to copy from the source track format -------
+ std::vector<AMediaFormatUtils::EntryCopier> srcParamsToCopy{
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_MIME, String),
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_DURATION, Int64),
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_WIDTH, Int32),
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_HEIGHT, Int32),
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_FRAME_RATE, Int32),
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_RANGE, Int32),
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_STANDARD, Int32),
+ ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_TRANSFER, Int32),
+ };
+
+ // If the destination codec is the same as the source codec, we can preserve profile and level
+ // from the source track as default values. Otherwise leave them unspecified.
+ const char *srcMime, *dstMime;
+ AMediaFormat_getString(srcFormat, AMEDIAFORMAT_KEY_MIME, &srcMime);
+ if (!AMediaFormat_getString(options, AMEDIAFORMAT_KEY_MIME, &dstMime) ||
+ strcmp(srcMime, dstMime) == 0) {
+ srcParamsToCopy.push_back(ENTRY_COPIER(AMEDIAFORMAT_KEY_PROFILE, String));
+ srcParamsToCopy.push_back(ENTRY_COPIER(AMEDIAFORMAT_KEY_LEVEL, String));
}
- // Note: AMediaFormat does not expose a function for appending values from another format or for
- // iterating over all values and keys in a format. Instead we define a static list of known keys
- // along with their value types and copy the ones that are present. A better solution would be
- // to either implement required functions in NDK or to parse the overlay format's string
- // representation and copy all existing keys.
- static const AMediaFormatUtils::EntryCopier kSupportedFormatEntries[] = {
+ // ------- Define parameters to copy from the caller's options -------
+ static const std::vector<AMediaFormatUtils::EntryCopier> kSupportedOptions{
ENTRY_COPIER(AMEDIAFORMAT_KEY_MIME, String),
ENTRY_COPIER(AMEDIAFORMAT_KEY_DURATION, Int64),
ENTRY_COPIER(AMEDIAFORMAT_KEY_WIDTH, Int32),
@@ -54,7 +67,6 @@
ENTRY_COPIER(AMEDIAFORMAT_KEY_BIT_RATE, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_PROFILE, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_LEVEL, Int32),
- ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_FORMAT, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_RANGE, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_STANDARD, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_TRANSFER, Int32),
@@ -63,10 +75,12 @@
ENTRY_COPIER(AMEDIAFORMAT_KEY_PRIORITY, Int32),
ENTRY_COPIER2(AMEDIAFORMAT_KEY_OPERATING_RATE, Float, Int32),
};
- const size_t entryCount = sizeof(kSupportedFormatEntries) / sizeof(kSupportedFormatEntries[0]);
- AMediaFormatUtils::CopyFormatEntries(overlay, format, kSupportedFormatEntries, entryCount);
- return format;
+ // ------- Copy parameters from source and options to the destination -------
+ auto trackFormat = std::shared_ptr<AMediaFormat>(AMediaFormat_new(), &AMediaFormat_delete);
+ AMediaFormatUtils::CopyFormatEntries(srcFormat, trackFormat.get(), srcParamsToCopy);
+ AMediaFormatUtils::CopyFormatEntries(options, trackFormat.get(), kSupportedOptions);
+ return trackFormat;
}
void MediaTranscoder::onThreadFinished(const void* thread, media_status_t threadStatus,
@@ -270,7 +284,8 @@
return trackFormats;
}
-media_status_t MediaTranscoder::configureTrackFormat(size_t trackIndex, AMediaFormat* trackFormat) {
+media_status_t MediaTranscoder::configureTrackFormat(size_t trackIndex,
+ AMediaFormat* destinationOptions) {
if (mSampleReader == nullptr) {
LOG(ERROR) << "Source must be configured before tracks";
return AMEDIA_ERROR_INVALID_OPERATION;
@@ -281,14 +296,15 @@
}
std::shared_ptr<MediaTrackTranscoder> transcoder;
- std::shared_ptr<AMediaFormat> format;
+ std::shared_ptr<AMediaFormat> trackFormat;
- if (trackFormat == nullptr) {
+ if (destinationOptions == nullptr) {
transcoder = std::make_shared<PassthroughTrackTranscoder>(shared_from_this());
} else {
+ AMediaFormat* srcTrackFormat = mSourceTrackFormats[trackIndex].get();
+
const char* srcMime = nullptr;
- if (!AMediaFormat_getString(mSourceTrackFormats[trackIndex].get(), AMEDIAFORMAT_KEY_MIME,
- &srcMime)) {
+ if (!AMediaFormat_getString(srcTrackFormat, AMEDIAFORMAT_KEY_MIME, &srcMime)) {
LOG(ERROR) << "Source track #" << trackIndex << " has no mime type";
return AMEDIA_ERROR_MALFORMED;
}
@@ -301,7 +317,7 @@
}
const char* dstMime = nullptr;
- if (AMediaFormat_getString(trackFormat, AMEDIAFORMAT_KEY_MIME, &dstMime)) {
+ if (AMediaFormat_getString(destinationOptions, AMEDIAFORMAT_KEY_MIME, &dstMime)) {
if (strncmp(dstMime, "video/", 6) != 0) {
LOG(ERROR) << "Unable to convert media types for track #" << trackIndex << ", from "
<< srcMime << " to " << dstMime;
@@ -311,14 +327,11 @@
transcoder = VideoTrackTranscoder::create(shared_from_this(), mPid, mUid);
- AMediaFormat* mergedFormat =
- mergeMediaFormats(mSourceTrackFormats[trackIndex].get(), trackFormat);
- if (mergedFormat == nullptr) {
- LOG(ERROR) << "Unable to merge source and destination formats";
+ trackFormat = createVideoTrackFormat(srcTrackFormat, destinationOptions);
+ if (trackFormat == nullptr) {
+ LOG(ERROR) << "Unable to create video track format";
return AMEDIA_ERROR_UNKNOWN;
}
-
- format = std::shared_ptr<AMediaFormat>(mergedFormat, &AMediaFormat_delete);
}
media_status_t status = mSampleReader->selectTrack(trackIndex);
@@ -327,7 +340,7 @@
return status;
}
- status = transcoder->configure(mSampleReader, trackIndex, format);
+ status = transcoder->configure(mSampleReader, trackIndex, trackFormat);
if (status != AMEDIA_OK) {
LOG(ERROR) << "Configure track transcoder for track #" << trackIndex << " returned error "
<< status;
diff --git a/media/libmediatranscoding/transcoder/NdkCommon.cpp b/media/libmediatranscoding/transcoder/NdkCommon.cpp
index fb909b2..2d85df7 100644
--- a/media/libmediatranscoding/transcoder/NdkCommon.cpp
+++ b/media/libmediatranscoding/transcoder/NdkCommon.cpp
@@ -60,19 +60,19 @@
DEFINE_FORMAT_VALUE_COPY_FUNC(int32_t, Int32);
DEFINE_FORMAT_VALUE_COPY_FUNC(float, Float);
-void CopyFormatEntries(AMediaFormat* from, AMediaFormat* to, const EntryCopier* entries,
- size_t entryCount) {
+void CopyFormatEntries(AMediaFormat* from, AMediaFormat* to,
+ const std::vector<EntryCopier>& entries) {
if (from == nullptr || to == nullptr) {
LOG(ERROR) << "Cannot copy null formats";
return;
- } else if (entries == nullptr || entryCount < 1) {
+ } else if (entries.empty()) {
LOG(WARNING) << "No entries to copy";
return;
}
- for (size_t i = 0; i < entryCount; ++i) {
- if (!entries[i].copy(entries[i].key, from, to) && entries[i].copy2 != nullptr) {
- entries[i].copy2(entries[i].key, from, to);
+ for (auto& entry : entries) {
+ if (!entry.copy(entry.key, from, to) && entry.copy2 != nullptr) {
+ entry.copy2(entry.key, from, to);
}
}
}
diff --git a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
index ab08d73..4405180 100644
--- a/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
+++ b/media/libmediatranscoding/transcoder/VideoTrackTranscoder.cpp
@@ -147,7 +147,7 @@
if (auto transcoder = wrapper->getTranscoder()) {
const bool isDecoder = codec == transcoder->mDecoder;
const char* kCodecName = (isDecoder ? "Decoder" : "Encoder");
- LOG(DEBUG) << kCodecName << " format changed: " << AMediaFormat_toString(format);
+ LOG(INFO) << kCodecName << " format changed: " << AMediaFormat_toString(format);
transcoder->mCodecMessageQueue.push([transcoder, format, isDecoder] {
transcoder->updateTrackFormat(format, isDecoder);
});
@@ -280,7 +280,7 @@
}
mEncoder = std::make_shared<CodecWrapper>(encoder, shared_from_this());
- LOG(DEBUG) << "Configuring encoder with: " << AMediaFormat_toString(mDestinationFormat.get());
+ LOG(INFO) << "Configuring encoder with: " << AMediaFormat_toString(mDestinationFormat.get());
status = AMediaCodec_configure(mEncoder->getCodec(), mDestinationFormat.get(),
NULL /* surface */, NULL /* crypto */,
AMEDIACODEC_CONFIGURE_FLAG_ENCODE);
@@ -332,15 +332,13 @@
AMediaFormat_setInt32(decoderFormat.get(), TBD_AMEDIACODEC_PARAMETER_KEY_ALLOW_FRAME_DROP, 0);
// Copy over configurations that apply to both encoder and decoder.
- static const EntryCopier kEncoderEntriesToCopy[] = {
+ static const std::vector<EntryCopier> kEncoderEntriesToCopy{
ENTRY_COPIER2(AMEDIAFORMAT_KEY_OPERATING_RATE, Float, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_PRIORITY, Int32),
};
- const size_t entryCount = sizeof(kEncoderEntriesToCopy) / sizeof(kEncoderEntriesToCopy[0]);
- CopyFormatEntries(mDestinationFormat.get(), decoderFormat.get(), kEncoderEntriesToCopy,
- entryCount);
+ CopyFormatEntries(mDestinationFormat.get(), decoderFormat.get(), kEncoderEntriesToCopy);
- LOG(DEBUG) << "Configuring decoder with: " << AMediaFormat_toString(decoderFormat.get());
+ LOG(INFO) << "Configuring decoder with: " << AMediaFormat_toString(decoderFormat.get());
status = AMediaCodec_configure(mDecoder, decoderFormat.get(), mSurface, NULL /* crypto */,
0 /* flags */);
if (status != AMEDIA_OK) {
@@ -487,9 +485,6 @@
onOutputSampleAvailable(sample);
mLastSampleWasSync = sample->info.flags & SAMPLE_FLAG_SYNC_SAMPLE;
- } else if (bufferIndex == AMEDIACODEC_INFO_OUTPUT_FORMAT_CHANGED) {
- AMediaFormat* newFormat = AMediaCodec_getOutputFormat(mEncoder->getCodec());
- LOG(DEBUG) << "Encoder output format changed: " << AMediaFormat_toString(newFormat);
}
if (bufferInfo.flags & AMEDIACODEC_BUFFER_FLAG_END_OF_STREAM) {
@@ -509,15 +504,14 @@
void VideoTrackTranscoder::updateTrackFormat(AMediaFormat* outputFormat, bool fromDecoder) {
if (fromDecoder) {
- static const AMediaFormatUtils::EntryCopier kValuesToCopy[] = {
+ static const std::vector<AMediaFormatUtils::EntryCopier> kValuesToCopy{
ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_RANGE, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_STANDARD, Int32),
ENTRY_COPIER(AMEDIAFORMAT_KEY_COLOR_TRANSFER, Int32),
};
AMediaFormat* params = AMediaFormat_new();
if (params != nullptr) {
- AMediaFormatUtils::CopyFormatEntries(outputFormat, params, kValuesToCopy,
- std::size(kValuesToCopy));
+ AMediaFormatUtils::CopyFormatEntries(outputFormat, params, kValuesToCopy);
if (AMediaCodec_setParameters(mEncoder->getCodec(), params) != AMEDIA_OK) {
LOG(WARNING) << "Unable to update encoder with color information";
}
@@ -589,7 +583,7 @@
// TODO: transfer other fields as required.
mActualOutputFormat = std::shared_ptr<AMediaFormat>(formatCopy, &AMediaFormat_delete);
- LOG(DEBUG) << "Actual output format: " << AMediaFormat_toString(formatCopy);
+ LOG(INFO) << "Actual output format: " << AMediaFormat_toString(formatCopy);
notifyTrackFormatAvailable();
}
diff --git a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h b/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
index a7ed6a7..c5547c6 100644
--- a/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
+++ b/media/libmediatranscoding/transcoder/include/media/NdkCommon.h
@@ -19,6 +19,8 @@
#include <media/NdkMediaFormat.h>
+#include <vector>
+
extern const char* AMEDIA_MIMETYPE_VIDEO_VP8;
extern const char* AMEDIA_MIMETYPE_VIDEO_VP9;
extern const char* AMEDIA_MIMETYPE_VIDEO_AV1;
@@ -82,8 +84,8 @@
bool CopyFormatEntryInt32(const char* key, AMediaFormat* from, AMediaFormat* to);
bool CopyFormatEntryFloat(const char* key, AMediaFormat* from, AMediaFormat* to);
-void CopyFormatEntries(AMediaFormat* from, AMediaFormat* to, const EntryCopier* entries,
- size_t entryCount);
+void CopyFormatEntries(AMediaFormat* from, AMediaFormat* to,
+ const std::vector<EntryCopier>& entries);
bool SetDefaultFormatValueFloat(const char* key, AMediaFormat* format, float value);
bool SetDefaultFormatValueInt32(const char* key, AMediaFormat* format, int32_t value);