stagefright: fix issues with bitrate handling
- parse btrt mp4 box
- write max and avg. bitrates into avcc
- fix the use of "bit-rate" vs. the correct "bitrate"
- document ESDS better
- fix some spacing
Bug: 28671284
Change-Id: I94961a095c6d162af38b7999cc946f899a1b1b09
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 4ae8e82..e59a498 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -1770,7 +1770,7 @@
mime.c_str(), audioFormat);
int avgBitRate = -1;
- format->findInt32("bit-rate", &avgBitRate);
+ format->findInt32("bitrate", &avgBitRate);
int32_t aacProfile = -1;
if (audioFormat == AUDIO_FORMAT_AAC
diff --git a/media/libstagefright/ESDS.cpp b/media/libstagefright/ESDS.cpp
index 8fbb57c..c31720d 100644
--- a/media/libstagefright/ESDS.cpp
+++ b/media/libstagefright/ESDS.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "ESDS"
#include <utils/Log.h>
+#include <media/stagefright/Utils.h>
+
#include "include/ESDS.h"
#include <string.h>
@@ -194,12 +196,25 @@
return err;
}
+status_t ESDS::getBitRate(uint32_t *brateMax, uint32_t *brateAvg) const {
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ *brateMax = mBitRateMax;
+ *brateAvg = mBitRateAvg;
+
+ return OK;
+};
+
status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) {
if (size < 13) {
return ERROR_MALFORMED;
}
mObjectTypeIndication = mData[offset];
+ mBitRateMax = U32_AT(mData + offset + 5);
+ mBitRateAvg = U32_AT(mData + offset + 9);
offset += 13;
size -= 13;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index f296d9a..935f3a9 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1738,6 +1738,31 @@
break;
}
+ case FOURCC('b', 't', 'r', 't'):
+ {
+ *offset += chunk_size;
+
+ uint8_t buffer[12];
+ if (chunk_data_size != sizeof(buffer)) {
+ return ERROR_MALFORMED;
+ }
+
+ if (mDataSource->readAt(
+ data_offset, buffer, chunk_data_size) < chunk_data_size) {
+ return ERROR_IO;
+ }
+
+ uint32_t maxBitrate = U32_AT(&buffer[4]);
+ uint32_t avgBitrate = U32_AT(&buffer[8]);
+ if (maxBitrate > 0 && maxBitrate < INT32_MAX) {
+ mLastTrack->meta->setInt32(kKeyMaxBitRate, (int32_t)maxBitrate);
+ }
+ if (avgBitrate > 0 && avgBitrate < INT32_MAX) {
+ mLastTrack->meta->setInt32(kKeyBitRate, (int32_t)avgBitrate);
+ }
+ break;
+ }
+
case FOURCC('a', 'v', 'c', 'C'):
{
*offset += chunk_size;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index db20590..7b98396 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -3057,11 +3057,14 @@
mOwner->writeInt8(0x15); // streamType AudioStream
mOwner->writeInt16(0x03); // XXX
- mOwner->writeInt8(0x00); // buffer size 24-bit
- int32_t bitRate;
- bool success = mMeta->findInt32(kKeyBitRate, &bitRate);
- mOwner->writeInt32(success ? bitRate : 96000); // max bit rate
- mOwner->writeInt32(success ? bitRate : 96000); // avg bit rate
+ mOwner->writeInt8(0x00); // buffer size 24-bit (0x300)
+
+ int32_t avgBitrate = 256000;
+ (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
+ int32_t maxBitrate = avgBitrate;
+ (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
+ mOwner->writeInt32(maxBitrate);
+ mOwner->writeInt32(avgBitrate);
mOwner->writeInt8(0x05); // DecoderSpecificInfoTag
mOwner->writeInt8(mCodecSpecificDataSize);
@@ -3095,12 +3098,17 @@
mOwner->writeInt8(0x11); // streamType VisualStream
static const uint8_t kData[] = {
- 0x01, 0x77, 0x00,
- 0x00, 0x03, 0xe8, 0x00,
- 0x00, 0x03, 0xe8, 0x00
+ 0x01, 0x77, 0x00, // buffer size 96000 bytes
};
mOwner->write(kData, sizeof(kData));
+ int32_t avgBitrate = 256000;
+ (void)mMeta->findInt32(kKeyBitRate, &avgBitrate);
+ int32_t maxBitrate = avgBitrate;
+ (void)mMeta->findInt32(kKeyMaxBitRate, &maxBitrate);
+ mOwner->writeInt32(maxBitrate);
+ mOwner->writeInt32(avgBitrate);
+
mOwner->writeInt8(0x05); // DecoderSpecificInfoTag
mOwner->writeInt8(mCodecSpecificDataSize);
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index 3e1badf..a347f00 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -157,9 +157,14 @@
msg->setInt64("durationUs", durationUs);
}
- int avgBitRate;
+ int32_t avgBitRate;
if (meta->findInt32(kKeyBitRate, &avgBitRate)) {
- msg->setInt32("bit-rate", avgBitRate);
+ msg->setInt32("bitrate", avgBitRate);
+ }
+
+ int32_t maxBitRate;
+ if (meta->findInt32(kKeyMaxBitRate, &maxBitRate)) {
+ msg->setInt32("max-bitrate", maxBitRate);
}
int32_t isSync;
@@ -465,6 +470,18 @@
buffer->meta()->setInt32("csd", true);
buffer->meta()->setInt64("timeUs", 0);
msg->setBuffer("csd-0", buffer);
+
+ uint32_t maxBitrate, avgBitrate;
+ if (esds.getBitRate(&maxBitrate, &avgBitrate) == OK) {
+ if (!meta->hasData(kKeyMaxBitRate)
+ && maxBitrate > 0 && maxBitrate <= INT32_MAX) {
+ msg->setInt32("max-bitrate", (int32_t)maxBitrate);
+ }
+ if (!meta->hasData(kKeyBitRate)
+ && avgBitrate > 0 && avgBitrate <= INT32_MAX) {
+ msg->setInt32("bitrate", (int32_t)avgBitrate);
+ }
+ }
} else if (meta->findData(kKeyVorbisInfo, &type, &data, &size)) {
sp<ABuffer> buffer = new (std::nothrow) ABuffer(size);
if (buffer.get() == NULL || buffer->base() == NULL) {
@@ -552,11 +569,10 @@
}
static size_t reassembleAVCC(const sp<ABuffer> &csd0, const sp<ABuffer> csd1, char *avcc) {
-
avcc[0] = 1; // version
- avcc[1] = 0x64; // profile
- avcc[2] = 0; // unused (?)
- avcc[3] = 0xd; // level
+ avcc[1] = 0x64; // profile (default to high)
+ avcc[2] = 0; // constraints (default to none)
+ avcc[3] = 0xd; // level (default to 1.3)
avcc[4] = 0xff; // reserved+size
size_t i = 0;
@@ -638,15 +654,16 @@
esds[11] = 0x80 | ((configdescriptorsize >> 7) & 0x7f);
esds[12] = (configdescriptorsize & 0x7f);
esds[13] = 0x40; // objectTypeIndication
- esds[14] = 0x15; // not sure what 14-25 mean, they are ignored by ESDS.cpp,
- esds[15] = 0x00; // but the actual values here were taken from a real file.
+ // bytes 14-25 are examples from a real file. they are unused/overwritten by muxers.
+ esds[14] = 0x15; // streamType(5), upStream(0),
+ esds[15] = 0x00; // 15-17: bufferSizeDB (6KB)
esds[16] = 0x18;
esds[17] = 0x00;
- esds[18] = 0x00;
+ esds[18] = 0x00; // 18-21: maxBitrate (64kbps)
esds[19] = 0x00;
esds[20] = 0xfa;
esds[21] = 0x00;
- esds[22] = 0x00;
+ esds[22] = 0x00; // 22-25: avgBitrate (64kbps)
esds[23] = 0x00;
esds[24] = 0xfa;
esds[25] = 0x00;
@@ -657,7 +674,6 @@
esds[30] = (csd0size & 0x7f);
memcpy((void*)&esds[31], csd0->data(), csd0size);
// data following this is ignored, so don't bother appending it
-
}
static size_t reassembleHVCC(const sp<ABuffer> &csd0, uint8_t *hvcc, size_t hvccSize, size_t nalSizeLength) {
@@ -1059,7 +1075,7 @@
int32_t brate = -1;
if (!meta->findInt32(kKeyBitRate, &brate)) {
ALOGV("track of type '%s' does not publish bitrate", mime);
- }
+ }
info.bit_rate = brate;