transcoder: fix rotation handling
Transfer rotation degree from source format to track format
for MediaSampleWriter, and setOrietationHint on the muxer.
During transcoding using encoder/decoder, clear the rotation
degree so that the codec is guaranted to operate non-rotated.
bug: 154734285
bug: 159649977
bug: 152091443
test: unit testing (updated test with rotation)
Change-Id: I7e829ef777b1954d894411e8591a5e31ff36e275
diff --git a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
index 9ffb32b..98813e7 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaSampleWriterTests.cpp
@@ -58,7 +58,7 @@
class TestMuxer : public MediaSampleWriterMuxerInterface {
public:
// MuxerInterface
- ssize_t addTrack(const AMediaFormat* trackFormat) override {
+ ssize_t addTrack(AMediaFormat* trackFormat) override {
mEventQueue.push_back(AddTrack(trackFormat));
return mTrackCount++;
}
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
index 4d9386a..71d3a4e 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTrackTranscoderTests.cpp
@@ -67,7 +67,7 @@
void initSampleReader() {
const char* sourcePath =
- "/data/local/tmp/TranscoderTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+ "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
const int sourceFd = open(sourcePath, O_RDONLY);
ASSERT_GT(sourceFd, 0);
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index 6bf6562..67f1ca1 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -40,7 +40,7 @@
struct FormatVerifierEntry {
const char* key;
- bool (*equal)(const char* key, AMediaFormat* src, AMediaFormat* dst);
+ std::function<bool(const char*, AMediaFormat*, AMediaFormat*)> equal;
};
static const FormatVerifierEntry kFieldsToPreserve[] = {
@@ -92,11 +92,6 @@
bool mFinished = false;
};
-static const char* SOURCE_PATH_AVC =
- "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
-static const char* SOURCE_PATH_HEVC =
- "/data/local/tmp/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4";
-
// Write-only, create file if non-existent, don't overwrite existing file.
static constexpr int kOpenFlags = O_WRONLY | O_CREAT | O_EXCL;
// User R+W permission.
@@ -161,6 +156,44 @@
return mCallbacks->mStatus;
}
+ void testTranscodeVideo(const char* srcPath, const char* destPath, const char* dstMime) {
+ const int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs
+
+ EXPECT_EQ(
+ transcodeHelper(
+ srcPath, destPath,
+ [dstMime](AMediaFormat* sourceFormat) {
+ AMediaFormat* format = nullptr;
+ const char* mime = nullptr;
+ AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
+
+ if (strncmp(mime, "video/", 6) == 0) {
+ format = AMediaFormat_new();
+ AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
+
+ if (dstMime != nullptr) {
+ AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, dstMime);
+ }
+ }
+ return format;
+ }),
+ AMEDIA_OK);
+
+ if (dstMime != nullptr) {
+ std::vector<FormatVerifierEntry> extraVerifiers = {
+ {AMEDIAFORMAT_KEY_MIME,
+ [dstMime](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
+ const char* mime = nullptr;
+ AMediaFormat_getString(dst, key, &mime);
+ return !strcmp(mime, dstMime);
+ }},
+ };
+ verifyOutputFormat(destPath, &extraVerifiers);
+ } else {
+ verifyOutputFormat(destPath);
+ }
+ }
+
void verifyOutputFormat(const char* destPath,
const std::vector<FormatVerifierEntry>* extraVerifiers = nullptr) {
int dstFd = open(destPath, O_RDONLY);
@@ -194,7 +227,8 @@
for (int i = 0; i < (sizeof(kFieldsToPreserve) / sizeof(kFieldsToPreserve[0])); ++i) {
EXPECT_TRUE(kFieldsToPreserve[i].equal(kFieldsToPreserve[i].key,
- mSourceVideoFormat.get(), videoFormat.get()));
+ mSourceVideoFormat.get(), videoFormat.get()))
+ << "Failed at key " << kFieldsToPreserve[i].key;
}
if (extraVerifiers != nullptr) {
@@ -212,76 +246,31 @@
};
TEST_F(MediaTranscoderTests, TestPassthrough) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
const char* destPath = "/data/local/tmp/MediaTranscoder_Passthrough.MP4";
- EXPECT_EQ(transcodeHelper(SOURCE_PATH_AVC, destPath, [](AMediaFormat*) { return nullptr; }),
- AMEDIA_OK);
+ EXPECT_EQ(transcodeHelper(srcPath, destPath, [](AMediaFormat*) { return nullptr; }), AMEDIA_OK);
verifyOutputFormat(destPath);
}
-TEST_F(MediaTranscoderTests, TestBasicVideoTranscodeAvcToAvc) {
- const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscodeAvcToAvc.MP4";
- const int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs
-
- EXPECT_EQ(transcodeHelper(
- SOURCE_PATH_AVC, destPath,
- [](AMediaFormat* sourceFormat) {
- AMediaFormat* format = nullptr;
- const char* mime = nullptr;
- AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
-
- if (strncmp(mime, "video/", 6) == 0) {
- format = AMediaFormat_new();
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
- }
- return format;
- }),
- AMEDIA_OK);
-
- std::vector<FormatVerifierEntry> extraVerifiers = {
- {AMEDIAFORMAT_KEY_MIME,
- [](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
- const char* mime = nullptr;
- AMediaFormat_getString(dst, key, &mime);
- return !strcmp(mime, AMEDIA_MIMETYPE_VIDEO_AVC);
- }},
- };
-
- verifyOutputFormat(destPath, &extraVerifiers);
+TEST_F(MediaTranscoderTests, TestVideoTranscode_AvcToAvc_Basic) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+ const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_AvcToAvc_Basic.MP4";
+ testTranscodeVideo(srcPath, destPath, nullptr /*dstMime*/);
}
-TEST_F(MediaTranscoderTests, TestBasicVideoTranscodeHevcToAvc) {
- const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscodeHevcToAvc.MP4";
+TEST_F(MediaTranscoderTests, TestVideoTranscode_HevcToAvc_Basic) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/jets_hevc_1280x720_20Mbps.mp4";
+ const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_HevcToAvc_Basic.MP4";
+ testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
+}
- EXPECT_EQ(transcodeHelper(
- SOURCE_PATH_HEVC, destPath,
- [](AMediaFormat* sourceFormat) {
- AMediaFormat* format = nullptr;
- const char* mime = nullptr;
- AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME, &mime);
-
- if (strncmp(mime, "video/", 6) == 0) {
- const int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs
- format = AMediaFormat_new();
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
- AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME,
- AMEDIA_MIMETYPE_VIDEO_AVC);
- }
- return format;
- }),
- AMEDIA_OK);
-
- std::vector<FormatVerifierEntry> extraVerifiers = {
- {AMEDIAFORMAT_KEY_MIME,
- [](const char* key, AMediaFormat* src __unused, AMediaFormat* dst) {
- const char* mime = nullptr;
- AMediaFormat_getString(dst, key, &mime);
- return !strcmp(mime, AMEDIA_MIMETYPE_VIDEO_AVC);
- }},
- };
-
- verifyOutputFormat(destPath, &extraVerifiers);
+TEST_F(MediaTranscoderTests, TestVideoTranscode_HevcToAvc_Rotation) {
+ const char* srcPath =
+ "/data/local/tmp/TranscodingTestAssets/desk_hevc_1920x1080_aac_48KHz_rot90.mp4";
+ const char* destPath = "/data/local/tmp/MediaTranscoder_VideoTranscode_HevcToAvc_Rotation.MP4";
+ testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
}
} // namespace android