Transcoder: Preserve source track's bitrate by default.
When no bitrate is passed in the transcoder now preserves the
source track's bitrate. If the bitrate is not available as metadata
the transcoder will sample the source track and estimate the bitrate.
Fixes: 160648740
Test: Unit tests.
Change-Id: I4e0284128aaa1116f5b61d908b52582b2ed3d7e4
diff --git a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
index e68eaac..53bd2a2 100644
--- a/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
+++ b/media/libmediatranscoding/transcoder/tests/MediaTranscoderTests.cpp
@@ -115,6 +115,17 @@
void deleteFile(const char* path) { unlink(path); }
+ float getFileSizeDiffPercent(const char* path1, const char* path2, bool absolute = false) {
+ struct stat s1, s2;
+ EXPECT_EQ(stat(path1, &s1), 0);
+ EXPECT_EQ(stat(path2, &s2), 0);
+
+ int64_t diff = s2.st_size - s1.st_size;
+ if (absolute && diff < 0) diff = -diff;
+
+ return (float)diff * 100.0f / s1.st_size;
+ }
+
using FormatConfigurationCallback = std::function<AMediaFormat*(AMediaFormat*)>;
media_status_t transcodeHelper(const char* srcPath, const char* destPath,
FormatConfigurationCallback formatCallback) {
@@ -157,28 +168,32 @@
return mCallbacks->mStatus;
}
- void testTranscodeVideo(const char* srcPath, const char* destPath, const char* dstMime) {
- const int32_t kBitRate = 8 * 1000 * 1000; // 8Mbs
+ void testTranscodeVideo(const char* srcPath, const char* destPath, const char* dstMime,
+ int32_t bitrate = 0) {
+ EXPECT_EQ(transcodeHelper(srcPath, destPath,
+ [dstMime, bitrate](AMediaFormat* sourceFormat) {
+ AMediaFormat* format = nullptr;
+ const char* mime = nullptr;
+ AMediaFormat_getString(sourceFormat, AMEDIAFORMAT_KEY_MIME,
+ &mime);
- 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 &&
+ (bitrate > 0 || dstMime != nullptr)) {
+ format = AMediaFormat_new();
- if (strncmp(mime, "video/", 6) == 0) {
- format = AMediaFormat_new();
- AMediaFormat_setInt32(format, AMEDIAFORMAT_KEY_BIT_RATE, kBitRate);
+ if (bitrate > 0) {
+ AMediaFormat_setInt32(
+ format, AMEDIAFORMAT_KEY_BIT_RATE, bitrate);
+ }
- if (dstMime != nullptr) {
- AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME, dstMime);
- }
- }
- return format;
- }),
- AMEDIA_OK);
+ if (dstMime != nullptr) {
+ AMediaFormat_setString(format, AMEDIAFORMAT_KEY_MIME,
+ dstMime);
+ }
+ }
+ return format;
+ }),
+ AMEDIA_OK);
if (dstMime != nullptr) {
std::vector<FormatVerifierEntry> extraVerifiers = {
@@ -251,16 +266,13 @@
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(srcPath, destPath, [](AMediaFormat*) { return nullptr; }), AMEDIA_OK);
-
- verifyOutputFormat(destPath);
+ testTranscodeVideo(srcPath, destPath, nullptr);
}
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*/);
+ testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
}
TEST_F(MediaTranscoderTests, TestVideoTranscode_HevcToAvc_Basic) {
@@ -276,6 +288,28 @@
testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
}
+TEST_F(MediaTranscoderTests, TestPreserveBitrate) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+ const char* destPath = "/data/local/tmp/MediaTranscoder_PreserveBitrate.MP4";
+ testTranscodeVideo(srcPath, destPath, AMEDIA_MIMETYPE_VIDEO_AVC);
+
+ // Require maximum of 10% difference in file size.
+ EXPECT_LT(getFileSizeDiffPercent(srcPath, destPath, true /* absolute*/), 10);
+}
+
+TEST_F(MediaTranscoderTests, TestCustomBitrate) {
+ const char* srcPath = "/data/local/tmp/TranscodingTestAssets/cubicle_avc_480x240_aac_24KHz.mp4";
+ const char* destPath1 = "/data/local/tmp/MediaTranscoder_CustomBitrate_2Mbps.MP4";
+ const char* destPath2 = "/data/local/tmp/MediaTranscoder_CustomBitrate_8Mbps.MP4";
+ testTranscodeVideo(srcPath, destPath1, AMEDIA_MIMETYPE_VIDEO_AVC, 2 * 1000 * 1000);
+ mCallbacks = std::make_shared<TestCallbacks>();
+ testTranscodeVideo(srcPath, destPath2, AMEDIA_MIMETYPE_VIDEO_AVC, 8 * 1000 * 1000);
+
+ // The source asset is very short and heavily compressed from the beginning so don't expect the
+ // requested bitrate to be exactly matched. However 40% difference seems reasonable.
+ EXPECT_GT(getFileSizeDiffPercent(destPath1, destPath2), 40);
+}
+
} // namespace android
int main(int argc, char** argv) {