summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Zhang <chz@google.com>2015-02-06 22:11:23 -0800
committerChong Zhang <chz@google.com>2015-02-12 14:02:24 -0800
commit78acc89eae9789366b6384707861f4563addf2d3 (patch)
treefd802dae4773a8cbffc6a7abb18fb8a485d68e84
parent9fdb3bd42af0876a9b76bae42d7aba2287b53af4 (diff)
downloadframeworks_av-78acc89eae9789366b6384707861f4563addf2d3.zip
frameworks_av-78acc89eae9789366b6384707861f4563addf2d3.tar.gz
frameworks_av-78acc89eae9789366b6384707861f4563addf2d3.tar.bz2
process all SEI messages for CC extraction
bug: 19297083 Change-Id: I5b89e35cc2bd5fb2f332872941e7978f15a6f403
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp66
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h1
-rw-r--r--media/libstagefright/include/avc_utils.h5
-rw-r--r--media/libstagefright/mpeg2ts/ESQueue.cpp25
4 files changed, 69 insertions, 28 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
index 9229704..cf3e8ad 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <inttypes.h>
+#include "avc_utils.h"
#include "NuPlayerCCDecoder.h"
#include <media/stagefright/foundation/ABitReader.h>
@@ -185,17 +186,38 @@ int32_t NuPlayer::CCDecoder::getTrackIndex(size_t channel) const {
// returns true if a new CC track is found
bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
- int64_t timeUs;
- CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
-
sp<ABuffer> sei;
if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) {
return false;
}
+ int64_t timeUs;
+ CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
+
bool trackAdded = false;
- NALBitReader br(sei->data() + 1, sei->size() - 1);
+ const NALPosition *nal = (NALPosition *) sei->data();
+
+ for (size_t i = 0; i < sei->size() / sizeof(NALPosition); ++i, ++nal) {
+ trackAdded |= parseSEINalUnit(
+ timeUs, accessUnit->data() + nal->nalOffset, nal->nalSize);
+ }
+
+ return trackAdded;
+}
+
+// returns true if a new CC track is found
+bool NuPlayer::CCDecoder::parseSEINalUnit(
+ int64_t timeUs, const uint8_t *nalStart, size_t nalSize) {
+ unsigned nalType = nalStart[0] & 0x1f;
+
+ // the buffer should only have SEI in it
+ if (nalType != 6) {
+ return false;
+ }
+
+ bool trackAdded = false;
+ NALBitReader br(nalStart + 1, nalSize - 1);
// sei_message()
while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message()
uint32_t payload_type = 0;
@@ -214,20 +236,25 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
// sei_payload()
if (payload_type == 4) {
- // user_data_registered_itu_t_t35()
-
- // ATSC A/72: 6.4.2
- uint8_t itu_t_t35_country_code = br.getBits(8);
- uint16_t itu_t_t35_provider_code = br.getBits(16);
- uint32_t user_identifier = br.getBits(32);
- uint8_t user_data_type_code = br.getBits(8);
-
- payload_size -= 1 + 2 + 4 + 1;
+ bool isCC = false;
+ if (payload_size > 1 + 2 + 4 + 1) {
+ // user_data_registered_itu_t_t35()
+
+ // ATSC A/72: 6.4.2
+ uint8_t itu_t_t35_country_code = br.getBits(8);
+ uint16_t itu_t_t35_provider_code = br.getBits(16);
+ uint32_t user_identifier = br.getBits(32);
+ uint8_t user_data_type_code = br.getBits(8);
+
+ payload_size -= 1 + 2 + 4 + 1;
+
+ isCC = itu_t_t35_country_code == 0xB5
+ && itu_t_t35_provider_code == 0x0031
+ && user_identifier == 'GA94'
+ && user_data_type_code == 0x3;
+ }
- if (itu_t_t35_country_code == 0xB5
- && itu_t_t35_provider_code == 0x0031
- && user_identifier == 'GA94'
- && user_data_type_code == 0x3) {
+ if (isCC && payload_size > 2) {
// MPEG_cc_data()
// ATSC A/53 Part 4: 6.2.3.1
br.skipBits(1); //process_em_data_flag
@@ -243,7 +270,7 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
sp<ABuffer> ccBuf = new ABuffer(cc_count * sizeof(CCData));
ccBuf->setRange(0, 0);
- for (size_t i = 0; i < cc_count; i++) {
+ for (size_t i = 0; i < cc_count && payload_size >= 3; i++) {
uint8_t marker = br.getBits(5);
CHECK_EQ(marker, 0x1f);
@@ -253,6 +280,8 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
uint8_t cc_data_1 = br.getBits(8) & 0x7f;
uint8_t cc_data_2 = br.getBits(8) & 0x7f;
+ payload_size -= 3;
+
if (cc_valid
&& (cc_type == 0 || cc_type == 1)) {
CCData cc(cc_type, cc_data_1, cc_data_2);
@@ -269,7 +298,6 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) {
}
}
}
- payload_size -= cc_count * 3;
mCCMap.add(timeUs, ccBuf);
break;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h
index 5e06f4e..77fb0fe 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h
@@ -49,6 +49,7 @@ private:
bool isTrackValid(size_t index) const;
int32_t getTrackIndex(size_t channel) const;
bool extractFromSEI(const sp<ABuffer> &accessUnit);
+ bool parseSEINalUnit(int64_t timeUs, const uint8_t *nalStart, size_t nalSize);
sp<ABuffer> filterCCBuf(const sp<ABuffer> &ccBuf, size_t index);
DISALLOW_EVIL_CONSTRUCTORS(CCDecoder);
diff --git a/media/libstagefright/include/avc_utils.h b/media/libstagefright/include/avc_utils.h
index c270bc1..dafa07e 100644
--- a/media/libstagefright/include/avc_utils.h
+++ b/media/libstagefright/include/avc_utils.h
@@ -36,6 +36,11 @@ enum {
kAVCProfileCAVLC444Intra = 0x2c
};
+struct NALPosition {
+ size_t nalOffset;
+ size_t nalSize;
+};
+
// Optionally returns sample aspect ratio as well.
void FindAVCDimensions(
const sp<ABuffer> &seqParamSet,
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 4cf3819..88da275 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -730,11 +730,6 @@ int64_t ElementaryStreamQueue::fetchTimestamp(size_t size) {
return timeUs;
}
-struct NALPosition {
- size_t nalOffset;
- size_t nalSize;
-};
-
sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
const uint8_t *data = mBuffer->data();
@@ -742,6 +737,7 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
Vector<NALPosition> nals;
size_t totalSize = 0;
+ size_t seiCount = 0;
status_t err;
const uint8_t *nalStart;
@@ -771,6 +767,9 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
// next frame.
flush = true;
+ } else if (nalType == 6 && nalSize > 0) {
+ // found non-zero sized SEI
+ ++seiCount;
}
if (flush) {
@@ -779,21 +778,29 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
size_t auSize = 4 * nals.size() + totalSize;
sp<ABuffer> accessUnit = new ABuffer(auSize);
+ sp<ABuffer> sei;
+
+ if (seiCount > 0) {
+ sei = new ABuffer(seiCount * sizeof(NALPosition));
+ accessUnit->meta()->setBuffer("sei", sei);
+ }
#if !LOG_NDEBUG
AString out;
#endif
size_t dstOffset = 0;
+ size_t seiIndex = 0;
for (size_t i = 0; i < nals.size(); ++i) {
const NALPosition &pos = nals.itemAt(i);
unsigned nalType = mBuffer->data()[pos.nalOffset] & 0x1f;
- if (nalType == 6) {
- sp<ABuffer> sei = new ABuffer(pos.nalSize);
- memcpy(sei->data(), mBuffer->data() + pos.nalOffset, pos.nalSize);
- accessUnit->meta()->setBuffer("sei", sei);
+ if (nalType == 6 && pos.nalSize > 0) {
+ CHECK_LT(seiIndex, sei->size() / sizeof(NALPosition));
+ NALPosition &seiPos = ((NALPosition *)sei->data())[seiIndex++];
+ seiPos.nalOffset = dstOffset + 4;
+ seiPos.nalSize = pos.nalSize;
}
#if !LOG_NDEBUG