17137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang/* 27137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * Copyright 2014 The Android Open Source Project 37137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * 47137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * Licensed under the Apache License, Version 2.0 (the "License"); 57137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * you may not use this file except in compliance with the License. 67137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * You may obtain a copy of the License at 77137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * 87137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * http://www.apache.org/licenses/LICENSE-2.0 97137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * 107137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * Unless required by applicable law or agreed to in writing, software 117137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * distributed under the License is distributed on an "AS IS" BASIS, 127137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * See the License for the specific language governing permissions and 147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang * limitations under the License. 157137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang */ 167137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 177137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang//#define LOG_NDEBUG 0 187137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#define LOG_TAG "NuPlayerCCDecoder" 197137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include <utils/Log.h> 207137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include <inttypes.h> 217137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2278acc89eae9789366b6384707861f4563addf2d3Chong Zhang#include "avc_utils.h" 237137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include "NuPlayerCCDecoder.h" 247137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 257137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include <media/stagefright/foundation/ABitReader.h> 267137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include <media/stagefright/foundation/ABuffer.h> 277137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include <media/stagefright/foundation/ADebug.h> 287137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include <media/stagefright/foundation/AMessage.h> 297137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#include <media/stagefright/MediaDefs.h> 307137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 317137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangnamespace android { 327137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 333694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung// In CEA-708B, the maximum bandwidth of CC is set to 9600bps. 343694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungstatic const size_t kMaxBandwithSizeBytes = 9600 / 8; 353694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 367137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangstruct CCData { 377137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang CCData(uint8_t type, uint8_t data1, uint8_t data2) 387137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang : mType(type), mData1(data1), mData2(data2) { 397137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 407137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang bool getChannel(size_t *channel) const { 417137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (mData1 >= 0x10 && mData1 <= 0x1f) { 427137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang *channel = (mData1 >= 0x18 ? 1 : 0) + (mType ? 2 : 0); 437137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return true; 447137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 457137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return false; 467137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 477137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 487137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang uint8_t mType; 497137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang uint8_t mData1; 507137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang uint8_t mData2; 517137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang}; 527137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 537137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangstatic bool isNullPad(CCData *cc) { 547137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return cc->mData1 < 0x10 && cc->mData2 < 0x10; 557137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 567137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 576d339f1f764bbd32e3381dae7bfa7c6c575bb493Lajos Molnarstatic void dumpBytePair(const sp<ABuffer> &ccBuf) __attribute__ ((unused)); 587137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangstatic void dumpBytePair(const sp<ABuffer> &ccBuf) { 597137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang size_t offset = 0; 607137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang AString out; 617137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 627137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang while (offset < ccBuf->size()) { 637137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang char tmp[128]; 647137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 657137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang CCData *cc = (CCData *) (ccBuf->data() + offset); 667137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 677137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (isNullPad(cc)) { 687137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // 1 null pad or XDS metadata, ignore 697137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang offset += sizeof(CCData); 707137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang continue; 717137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 727137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 737137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (cc->mData1 >= 0x20 && cc->mData1 <= 0x7f) { 747137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // 2 basic chars 752c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]Basic: %c %c", cc->mType, cc->mData1, cc->mData2); 767137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19) 777137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && cc->mData2 >= 0x30 && cc->mData2 <= 0x3f) { 787137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // 1 special char 792c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]Special: %02x %02x", cc->mType, cc->mData1, cc->mData2); 807137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else if ((cc->mData1 == 0x12 || cc->mData1 == 0x1A) 817137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){ 827137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // 1 Spanish/French char 832c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]Spanish: %02x %02x", cc->mType, cc->mData1, cc->mData2); 847137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else if ((cc->mData1 == 0x13 || cc->mData1 == 0x1B) 857137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && cc->mData2 >= 0x20 && cc->mData2 <= 0x3f){ 867137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // 1 Portuguese/German/Danish char 872c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]German: %02x %02x", cc->mType, cc->mData1, cc->mData2); 887137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else if ((cc->mData1 == 0x11 || cc->mData1 == 0x19) 897137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f){ 907137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // Mid-Row Codes (Table 69) 912c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]Mid-row: %02x %02x", cc->mType, cc->mData1, cc->mData2); 927137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else if (((cc->mData1 == 0x14 || cc->mData1 == 0x1c) 937137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && cc->mData2 >= 0x20 && cc->mData2 <= 0x2f) 947137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang || 957137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ((cc->mData1 == 0x17 || cc->mData1 == 0x1f) 967137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && cc->mData2 >= 0x21 && cc->mData2 <= 0x23)){ 977137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // Misc Control Codes (Table 70) 982c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]Ctrl: %02x %02x", cc->mType, cc->mData1, cc->mData2); 997137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else if ((cc->mData1 & 0x70) == 0x10 1007137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && (cc->mData2 & 0x40) == 0x40 1017137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang && ((cc->mData1 & 0x07) || !(cc->mData2 & 0x20)) ) { 1027137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // Preamble Address Codes (Table 71) 1032c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]PAC: %02x %02x", cc->mType, cc->mData1, cc->mData2); 1047137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else { 1052c9cb62d0160fc4353d89fd9d648725794e7995eGeorge Burgess IV snprintf(tmp, sizeof(tmp), "[%d]Invalid: %02x %02x", cc->mType, cc->mData1, cc->mData2); 1067137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1077137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1087137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (out.size() > 0) { 1097137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang out.append(", "); 1107137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1117137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1127137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang out.append(tmp); 1137137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang offset += sizeof(CCData); 1157137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1167137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1177137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGI("%s", out.c_str()); 1187137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 1197137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1207137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong ZhangNuPlayer::CCDecoder::CCDecoder(const sp<AMessage> ¬ify) 1217137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang : mNotify(notify), 1223694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mSelectedTrack(-1), 1233694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mDTVCCPacket(new ABuffer(kMaxBandwithSizeBytes)) { 1243694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mDTVCCPacket->setRange(0, 0); 1253694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 1263694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // In CEA-608, streams from packets which have the value 0 of cc_type contain CC1 and CC2, and 1273694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // streams from packets which have the value 1 of cc_type contain CC3 and CC4. 1283694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // The following array indicates the current transmitting channels for each value of cc_type. 1293694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mLine21Channels[0] = 0; // CC1 1303694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mLine21Channels[1] = 2; // CC3 1317137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 1327137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1337137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangsize_t NuPlayer::CCDecoder::getTrackCount() const { 1343694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return mTracks.size(); 1357137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 1367137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1377137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangsp<AMessage> NuPlayer::CCDecoder::getTrackInfo(size_t index) const { 1387137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (!isTrackValid(index)) { 1397137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return NULL; 1407137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1417137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1427137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang sp<AMessage> format = new AMessage(); 1437137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1443694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung CCTrack track = mTracks[index]; 1453694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 1467137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang format->setInt32("type", MEDIA_TRACK_TYPE_SUBTITLE); 1477137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang format->setString("language", "und"); 1483694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 1493694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung switch (track.mTrackType) { 1503694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung case kTrackTypeCEA608: 1513694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_608); 1523694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung break; 1533694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung case kTrackTypeCEA708: 1543694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung format->setString("mime", MEDIA_MIMETYPE_TEXT_CEA_708); 1553694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung break; 1563694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung default: 1573694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ALOGE("Unknown track type: %d", track.mTrackType); 1583694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return NULL; 1593694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 1603694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 1613694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // For CEA-608 CC1, field 0 channel 0 1623694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung bool isDefaultAuto = track.mTrackType == kTrackTypeCEA608 1633694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung && track.mTrackChannel == 0; 1643694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // For CEA-708, Primary Caption Service. 1653694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung bool isDefaultOnly = track.mTrackType == kTrackTypeCEA708 1663694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung && track.mTrackChannel == 1; 1677137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang format->setInt32("auto", isDefaultAuto); 1683694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung format->setInt32("default", isDefaultAuto || isDefaultOnly); 1697137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang format->setInt32("forced", 0); 1707137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1717137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return format; 1727137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 1737137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1747137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangstatus_t NuPlayer::CCDecoder::selectTrack(size_t index, bool select) { 1757137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (!isTrackValid(index)) { 1767137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return BAD_VALUE; 1777137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1787137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1797137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (select) { 1807137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (mSelectedTrack == (ssize_t)index) { 1817137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGE("track %zu already selected", index); 1827137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return BAD_VALUE; 1837137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1847137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGV("selected track %zu", index); 1857137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mSelectedTrack = index; 1867137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else { 1877137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (mSelectedTrack != (ssize_t)index) { 1887137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGE("track %zu is not selected", index); 1897137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return BAD_VALUE; 1907137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1917137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGV("unselected track %zu", index); 1927137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mSelectedTrack = -1; 1937137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 1947137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 1953694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // Clear the previous track payloads 1963694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mCCMap.clear(); 1973694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 1987137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return OK; 1997137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 2007137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2017137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangbool NuPlayer::CCDecoder::isSelected() const { 2023694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return mSelectedTrack >= 0 && mSelectedTrack < (int32_t)getTrackCount(); 2037137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 2047137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2057137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangbool NuPlayer::CCDecoder::isTrackValid(size_t index) const { 2067137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return index < getTrackCount(); 2077137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 2087137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2097137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang// returns true if a new CC track is found 2107137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangbool NuPlayer::CCDecoder::extractFromSEI(const sp<ABuffer> &accessUnit) { 2117137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang sp<ABuffer> sei; 2127137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (!accessUnit->meta()->findBuffer("sei", &sei) || sei == NULL) { 2137137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return false; 2147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 2157137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 21678acc89eae9789366b6384707861f4563addf2d3Chong Zhang int64_t timeUs; 21778acc89eae9789366b6384707861f4563addf2d3Chong Zhang CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 21878acc89eae9789366b6384707861f4563addf2d3Chong Zhang 2197137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang bool trackAdded = false; 2207137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2213694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung const NALPosition *nal = (NALPosition *)sei->data(); 22278acc89eae9789366b6384707861f4563addf2d3Chong Zhang 22378acc89eae9789366b6384707861f4563addf2d3Chong Zhang for (size_t i = 0; i < sei->size() / sizeof(NALPosition); ++i, ++nal) { 22478acc89eae9789366b6384707861f4563addf2d3Chong Zhang trackAdded |= parseSEINalUnit( 22578acc89eae9789366b6384707861f4563addf2d3Chong Zhang timeUs, accessUnit->data() + nal->nalOffset, nal->nalSize); 22678acc89eae9789366b6384707861f4563addf2d3Chong Zhang } 22778acc89eae9789366b6384707861f4563addf2d3Chong Zhang 22878acc89eae9789366b6384707861f4563addf2d3Chong Zhang return trackAdded; 22978acc89eae9789366b6384707861f4563addf2d3Chong Zhang} 23078acc89eae9789366b6384707861f4563addf2d3Chong Zhang 23178acc89eae9789366b6384707861f4563addf2d3Chong Zhang// returns true if a new CC track is found 2323694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::parseSEINalUnit(int64_t timeUs, const uint8_t *data, size_t size) { 2333694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung unsigned nalType = data[0] & 0x1f; 23478acc89eae9789366b6384707861f4563addf2d3Chong Zhang 23578acc89eae9789366b6384707861f4563addf2d3Chong Zhang // the buffer should only have SEI in it 23678acc89eae9789366b6384707861f4563addf2d3Chong Zhang if (nalType != 6) { 23778acc89eae9789366b6384707861f4563addf2d3Chong Zhang return false; 23878acc89eae9789366b6384707861f4563addf2d3Chong Zhang } 23978acc89eae9789366b6384707861f4563addf2d3Chong Zhang 24078acc89eae9789366b6384707861f4563addf2d3Chong Zhang bool trackAdded = false; 2413694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung NALBitReader br(data + 1, size - 1); 2423694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 2437137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // sei_message() 2447137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang while (br.atLeastNumBitsLeft(16)) { // at least 16-bit for sei_message() 2457137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang uint32_t payload_type = 0; 2467137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang size_t payload_size = 0; 2477137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang uint8_t last_byte; 2487137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2497137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang do { 2507137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang last_byte = br.getBits(8); 2517137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang payload_type += last_byte; 2527137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } while (last_byte == 0xFF); 2537137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2547137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang do { 2557137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang last_byte = br.getBits(8); 2567137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang payload_size += last_byte; 2577137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } while (last_byte == 0xFF); 2587137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 259303a2c2b7c321947fa6032893de3ed8a3d6e93eePatrik if (payload_size > SIZE_MAX / 8 260303a2c2b7c321947fa6032893de3ed8a3d6e93eePatrik || !br.atLeastNumBitsLeft(payload_size * 8)) { 261303a2c2b7c321947fa6032893de3ed8a3d6e93eePatrik ALOGV("Malformed SEI payload"); 262303a2c2b7c321947fa6032893de3ed8a3d6e93eePatrik break; 263303a2c2b7c321947fa6032893de3ed8a3d6e93eePatrik } 264303a2c2b7c321947fa6032893de3ed8a3d6e93eePatrik 2657137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // sei_payload() 2667137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (payload_type == 4) { 26778acc89eae9789366b6384707861f4563addf2d3Chong Zhang bool isCC = false; 26878acc89eae9789366b6384707861f4563addf2d3Chong Zhang if (payload_size > 1 + 2 + 4 + 1) { 26978acc89eae9789366b6384707861f4563addf2d3Chong Zhang // user_data_registered_itu_t_t35() 27078acc89eae9789366b6384707861f4563addf2d3Chong Zhang 27178acc89eae9789366b6384707861f4563addf2d3Chong Zhang // ATSC A/72: 6.4.2 27278acc89eae9789366b6384707861f4563addf2d3Chong Zhang uint8_t itu_t_t35_country_code = br.getBits(8); 27378acc89eae9789366b6384707861f4563addf2d3Chong Zhang uint16_t itu_t_t35_provider_code = br.getBits(16); 27478acc89eae9789366b6384707861f4563addf2d3Chong Zhang uint32_t user_identifier = br.getBits(32); 27578acc89eae9789366b6384707861f4563addf2d3Chong Zhang uint8_t user_data_type_code = br.getBits(8); 27678acc89eae9789366b6384707861f4563addf2d3Chong Zhang 27778acc89eae9789366b6384707861f4563addf2d3Chong Zhang payload_size -= 1 + 2 + 4 + 1; 27878acc89eae9789366b6384707861f4563addf2d3Chong Zhang 27978acc89eae9789366b6384707861f4563addf2d3Chong Zhang isCC = itu_t_t35_country_code == 0xB5 28078acc89eae9789366b6384707861f4563addf2d3Chong Zhang && itu_t_t35_provider_code == 0x0031 28178acc89eae9789366b6384707861f4563addf2d3Chong Zhang && user_identifier == 'GA94' 28278acc89eae9789366b6384707861f4563addf2d3Chong Zhang && user_data_type_code == 0x3; 28378acc89eae9789366b6384707861f4563addf2d3Chong Zhang } 2847137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 28578acc89eae9789366b6384707861f4563addf2d3Chong Zhang if (isCC && payload_size > 2) { 2863694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung trackAdded |= parseMPEGCCData(timeUs, br.data(), br.numBitsLeft() / 8); 2877137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else { 2887137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGV("Malformed SEI payload type 4"); 2897137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 2907137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } else { 2917137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGV("Unsupported SEI payload type %d", payload_type); 2927137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 2937137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2947137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // skipping remaining bits of this payload 2957137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang br.skipBits(payload_size * 8); 2967137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 2977137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 2987137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return trackAdded; 2997137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 3007137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 3013694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung// returns true if a new CC track is found 3023694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::extractFromMPEGUserData(const sp<ABuffer> &accessUnit) { 3033694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung sp<ABuffer> mpegUserData; 3043694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (!accessUnit->meta()->findBuffer("mpegUserData", &mpegUserData) 3053694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung || mpegUserData == NULL) { 3063694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return false; 3073694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3083694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3093694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung int64_t timeUs; 3103694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs)); 3113694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3123694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung bool trackAdded = false; 3133694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3143694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung const size_t *userData = (size_t *)mpegUserData->data(); 3153694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3163694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung for (size_t i = 0; i < mpegUserData->size() / sizeof(size_t); ++i) { 3173694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung trackAdded |= parseMPEGUserDataUnit( 3183694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung timeUs, accessUnit->data() + userData[i], accessUnit->size() - userData[i]); 3193694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3203694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3213694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return trackAdded; 3223694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 3233694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3243694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung// returns true if a new CC track is found 3253694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::parseMPEGUserDataUnit(int64_t timeUs, const uint8_t *data, size_t size) { 3263694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ABitReader br(data + 4, 5); 3273694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3283694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung uint32_t user_identifier = br.getBits(32); 3293694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung uint8_t user_data_type = br.getBits(8); 3303694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3313694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (user_identifier == 'GA94' && user_data_type == 0x3) { 3323694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return parseMPEGCCData(timeUs, data + 9, size - 9); 3333694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3343694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3353694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return false; 3363694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 3373694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3383694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung// returns true if a new CC track is found 3393694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::parseMPEGCCData(int64_t timeUs, const uint8_t *data, size_t size) { 3403694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung bool trackAdded = false; 3413694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3423694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // MPEG_cc_data() 3433694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // ATSC A/53 Part 4: 6.2.3.1 3443694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ABitReader br(data, size); 3453694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3463694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (br.numBitsLeft() <= 16) { 3473694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return false; 3483694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3493694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3503694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(1); 3513694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung bool process_cc_data_flag = br.getBits(1); 3523694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(1); 3533694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung size_t cc_count = br.getBits(5); 3543694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(8); 3553694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3563694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (!process_cc_data_flag || 3 * 8 * cc_count >= br.numBitsLeft()) { 3573694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return false; 3583694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3593694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3603694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung sp<ABuffer> line21CCBuf = NULL; 3617137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 3627137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang for (size_t i = 0; i < cc_count; ++i) { 3633694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(5); 3643694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung bool cc_valid = br.getBits(1); 3653694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung uint8_t cc_type = br.getBits(2); 3663694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3673694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (cc_valid) { 3683694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (cc_type == 3) { 3693694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (mDTVCCPacket->size() > 0) { 3703694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung trackAdded |= parseDTVCCPacket( 3713694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung timeUs, mDTVCCPacket->data(), mDTVCCPacket->size()); 3723694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mDTVCCPacket->setRange(0, 0); 3733694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3743694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung memcpy(mDTVCCPacket->data() + mDTVCCPacket->size(), br.data(), 2); 3753694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mDTVCCPacket->setRange(0, mDTVCCPacket->size() + 2); 3763694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(16); 3773694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } else if (mDTVCCPacket->size() > 0 && cc_type == 2) { 3783694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung memcpy(mDTVCCPacket->data() + mDTVCCPacket->size(), br.data(), 2); 3793694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mDTVCCPacket->setRange(0, mDTVCCPacket->size() + 2); 3803694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(16); 3813694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } else if (cc_type == 0 || cc_type == 1) { 3823694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung uint8_t cc_data_1 = br.getBits(8) & 0x7f; 3833694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung uint8_t cc_data_2 = br.getBits(8) & 0x7f; 3843694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3853694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung CCData cc(cc_type, cc_data_1, cc_data_2); 3863694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3873694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (isNullPad(&cc)) { 3883694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung continue; 3893694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3903694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3913694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung size_t channel; 3923694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (cc.getChannel(&channel)) { 3933694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mLine21Channels[cc_type] = channel; 3943694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3953694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // create a new track if it does not exist. 3963694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung getTrackIndex(kTrackTypeCEA608, channel, &trackAdded); 3973694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 3983694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 3993694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (isSelected() && mTracks[mSelectedTrack].mTrackType == kTrackTypeCEA608 4003694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung && mTracks[mSelectedTrack].mTrackChannel == mLine21Channels[cc_type]) { 4013694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (line21CCBuf == NULL) { 4023694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung line21CCBuf = new ABuffer((cc_count - i) * sizeof(CCData)); 4033694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung line21CCBuf->setRange(0, 0); 4043694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4053694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung memcpy(line21CCBuf->data() + line21CCBuf->size(), &cc, sizeof(cc)); 4063694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung line21CCBuf->setRange(0, line21CCBuf->size() + sizeof(CCData)); 4073694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4083694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } else { 4093694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(16); 4103694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4113694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } else { 4123694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if ((cc_type == 3 || cc_type == 2) && mDTVCCPacket->size() > 0) { 4133694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung trackAdded |= parseDTVCCPacket(timeUs, mDTVCCPacket->data(), mDTVCCPacket->size()); 4143694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mDTVCCPacket->setRange(0, 0); 4153694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4163694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(16); 4173694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4183694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4193694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4203694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (isSelected() && mTracks[mSelectedTrack].mTrackType == kTrackTypeCEA608 4213694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung && line21CCBuf != NULL && line21CCBuf->size() > 0) { 4223694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mCCMap.add(timeUs, line21CCBuf); 4233694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4243694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4253694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return trackAdded; 4263694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 4273694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4283694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung// returns true if a new CC track is found 4293694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::parseDTVCCPacket(int64_t timeUs, const uint8_t *data, size_t size) { 4303694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // CEA-708B 5 DTVCC Packet Layer. 4313694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ABitReader br(data, size); 4323694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(2); 4333694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4343694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung size_t packet_size = br.getBits(6); 4353694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (packet_size == 0) packet_size = 64; 4363694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung packet_size *= 2; 4373694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4383694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (size != packet_size) { 4393694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return false; 4403694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4413694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4423694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung bool trackAdded = false; 4433694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4443694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung while (br.numBitsLeft() >= 16) { 4453694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // CEA-708B Figure 5 and 6. 4463694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung uint8_t service_number = br.getBits(3); 4473694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung size_t block_size = br.getBits(5); 4483694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4493694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (service_number == 64) { 4503694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(2); 4513694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung service_number = br.getBits(6); 4523694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4533694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (service_number < 64) { 4543694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return trackAdded; 4553694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4563694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4573694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4583694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (br.numBitsLeft() < block_size * 8) { 4593694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return trackAdded; 4607137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 4613694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4623694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (block_size > 0) { 4633694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung size_t trackIndex = getTrackIndex(kTrackTypeCEA708, service_number, &trackAdded); 4643694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (mSelectedTrack == (ssize_t)trackIndex) { 4653694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung sp<ABuffer> ccPacket = new ABuffer(block_size); 4663694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung memcpy(ccPacket->data(), br.data(), block_size); 4673694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mCCMap.add(timeUs, ccPacket); 4683694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4697137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 4703694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung br.skipBits(block_size * 8); 4717137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 4727137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 4733694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return trackAdded; 4743694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 4753694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4763694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung// return the track index for a given type and channel. 4773694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung// if the track does not exist, creates a new one. 4783694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungsize_t NuPlayer::CCDecoder::getTrackIndex( 4793694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung int32_t trackType, size_t channel, bool *trackAdded) { 4803694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung CCTrack track(trackType, channel); 4813694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ssize_t index = mTrackIndices.indexOfKey(track); 4823694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4833694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (index < 0) { 4843694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung // A new track is added. 4853694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung index = mTracks.size(); 4863694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mTrackIndices.add(track, index); 4873694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mTracks.add(track); 4883694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung *trackAdded = true; 4893694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return index; 4903694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 4913694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 4923694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return mTrackIndices.valueAt(index); 4937137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 4947137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 4957137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::CCDecoder::decode(const sp<ABuffer> &accessUnit) { 4963694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (extractFromMPEGUserData(accessUnit) || extractFromSEI(accessUnit)) { 4977137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang sp<AMessage> msg = mNotify->dup(); 4987137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang msg->setInt32("what", kWhatTrackAdded); 4997137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang msg->post(); 5007137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 5017137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // TODO: extract CC from other sources 5027137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 5037137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5047137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::CCDecoder::display(int64_t timeUs) { 5053694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (!isSelected()) { 5067137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return; 5077137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 5087137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5097137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ssize_t index = mCCMap.indexOfKey(timeUs); 5107137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (index < 0) { 5117137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ALOGV("cc for timestamp %" PRId64 " not found", timeUs); 5127137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang return; 5137137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 5147137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5153694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung sp<ABuffer> ccBuf; 5163694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5173694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (index == 0) { 5183694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ccBuf = mCCMap.valueAt(index); 5193694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } else { 5203694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung size_t size = 0; 5213694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5223694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung for (ssize_t i = 0; i <= index; ++i) { 5233694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung size += mCCMap.valueAt(i)->size(); 5243694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 5253694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5263694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ccBuf = new ABuffer(size); 5273694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ccBuf->setRange(0, 0); 5283694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5293694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung for (ssize_t i = 0; i <= index; ++i) { 5303694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung sp<ABuffer> buf = mCCMap.valueAt(i); 5313694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung memcpy(ccBuf->data() + ccBuf->size(), buf->data(), buf->size()); 5323694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung ccBuf->setRange(0, ccBuf->size() + buf->size()); 5333694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 5343694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung } 5357137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5367137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang if (ccBuf->size() > 0) { 5377137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#if 0 5387137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang dumpBytePair(ccBuf); 5397137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang#endif 5407137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5417137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ccBuf->meta()->setInt32("trackIndex", mSelectedTrack); 5427137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ccBuf->meta()->setInt64("timeUs", timeUs); 5437137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang ccBuf->meta()->setInt64("durationUs", 0ll); 5447137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5457137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang sp<AMessage> msg = mNotify->dup(); 5467137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang msg->setInt32("what", kWhatClosedCaptionData); 5477137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang msg->setBuffer("buffer", ccBuf); 5487137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang msg->post(); 5497137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang } 5507137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5517137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang // remove all entries before timeUs 5527137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mCCMap.removeItemsAt(0, index + 1); 5537137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 5547137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5557137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhangvoid NuPlayer::CCDecoder::flush() { 5567137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang mCCMap.clear(); 5573694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung mDTVCCPacket->setRange(0, 0); 5583694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 5593694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5603694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungint32_t NuPlayer::CCDecoder::CCTrack::compare(const NuPlayer::CCDecoder::CCTrack& rhs) const { 5613694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung int32_t cmp = mTrackType - rhs.mTrackType; 5623694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung if (cmp != 0) return cmp; 5633694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return mTrackChannel - rhs.mTrackChannel; 5643694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 5653694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5663694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::CCTrack::operator<(const NuPlayer::CCDecoder::CCTrack& rhs) const { 5673694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return compare(rhs) < 0; 5683694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 5693694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5703694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::CCTrack::operator==(const NuPlayer::CCDecoder::CCTrack& rhs) const { 5713694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return compare(rhs) == 0; 5723694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung} 5733694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung 5743694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chungbool NuPlayer::CCDecoder::CCTrack::operator!=(const NuPlayer::CCDecoder::CCTrack& rhs) const { 5753694d7cf40d1645bf05246cf38595eed606bb650Jaesung Chung return compare(rhs) != 0; 5767137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} 5777137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 5787137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang} // namespace android 5797137ec7e005a5a6e3c0edb91cfacf16a31f4bf6aChong Zhang 580