Loading media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp +47 −19 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <utils/Log.h> #include <inttypes.h> #include "avc_utils.h" #include "NuPlayerCCDecoder.h" #include <media/stagefright/foundation/ABitReader.h> Loading Loading @@ -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; Loading @@ -214,6 +236,8 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { // sei_payload() if (payload_type == 4) { bool isCC = false; if (payload_size > 1 + 2 + 4 + 1) { // user_data_registered_itu_t_t35() // ATSC A/72: 6.4.2 Loading @@ -224,10 +248,13 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { payload_size -= 1 + 2 + 4 + 1; if (itu_t_t35_country_code == 0xB5 isCC = itu_t_t35_country_code == 0xB5 && itu_t_t35_provider_code == 0x0031 && user_identifier == 'GA94' && user_data_type_code == 0x3) { && 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 Loading @@ -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); Loading @@ -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); Loading @@ -269,7 +298,6 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { } } } payload_size -= cc_count * 3; mCCMap.add(timeUs, ccBuf); break; Loading media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading media/libstagefright/include/avc_utils.h +5 −0 Original line number Diff line number Diff line Loading @@ -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, Loading media/libstagefright/mpeg2ts/ESQueue.cpp +16 −9 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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 Loading Loading
media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.cpp +47 −19 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <utils/Log.h> #include <inttypes.h> #include "avc_utils.h" #include "NuPlayerCCDecoder.h" #include <media/stagefright/foundation/ABitReader.h> Loading Loading @@ -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; Loading @@ -214,6 +236,8 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { // sei_payload() if (payload_type == 4) { bool isCC = false; if (payload_size > 1 + 2 + 4 + 1) { // user_data_registered_itu_t_t35() // ATSC A/72: 6.4.2 Loading @@ -224,10 +248,13 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { payload_size -= 1 + 2 + 4 + 1; if (itu_t_t35_country_code == 0xB5 isCC = itu_t_t35_country_code == 0xB5 && itu_t_t35_provider_code == 0x0031 && user_identifier == 'GA94' && user_data_type_code == 0x3) { && 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 Loading @@ -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); Loading @@ -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); Loading @@ -269,7 +298,6 @@ bool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { } } } payload_size -= cc_count * 3; mCCMap.add(timeUs, ccBuf); break; Loading
media/libmediaplayerservice/nuplayer/NuPlayerCCDecoder.h +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
media/libstagefright/include/avc_utils.h +5 −0 Original line number Diff line number Diff line Loading @@ -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, Loading
media/libstagefright/mpeg2ts/ESQueue.cpp +16 −9 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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 Loading