MPEG2TSExtractor简析


1. 简介

      在本篇文章中, 我会详细的记录我学习MPEG2TSExtractor的全部过程. 与其说是一篇技术博客, 不如说是一篇学习笔记吧. 纯属爱好而已. 万事开头难, 那我们就先从“它是怎么来滴”入手把。


2. 从"MPEG2TSExtractor出生"开始

      按照惯例, 我们从构造函数看起.

115 MPEG2TSExtractor::MPEG2TSExtractor(const sp &source)
116    : mDataSource(source),
117      mParser(new ATSParser),
118      mLastSyncEvent(0),
119      mOffset(0) {
120    init();
121 }
  1. 将DataSource传进来(DataSource就是文件源);
  2. 然后创建一个ATSParse, 这个类是负责具体来parse数据的;
  3. mLastSyncEvent初始化为0, 他是干嘛的? 看看官方解释:
62    // Used to remember SyncEvent occurred in feedMore() when called from init(),
63    // because init() needs to update |mSourceImpls| before adding SyncPoint.

      我想应该是用来用于seek的吧.

  1. 接着是mOffset初始化为0, 他代表着当前读取文件源的偏移量;
  2. 调用init(), 进行初始化.

2.1 MPEG2TSExtractor::init()

      init()方法多达180多行, 这着实让小弟十分为难, 肿么办呢, 嫌麻烦的童鞋就直接看代码下方小弟的个人见解吧.

183 void MPEG2TSExtractor::init() {
184    bool haveAudio = false;
185    bool haveVideo = false;
186    int64_t startTime = ALooper::GetNowUs();
187
188    status_t err;
189    while ((err = feedMore(true /* isInit */)) == OK
190            || err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
191        if (haveAudio && haveVideo) {
192            addSyncPoint_l(mLastSyncEvent);
193            mLastSyncEvent.reset();
194            break;
195        }
196        if (!haveVideo) {
197            sp impl =
198                (AnotherPacketSource *)mParser->getSource(
199                        ATSParser::VIDEO).get();
200
201            if (impl != NULL) {
202                sp format = impl->getFormat();
203                if (format != NULL) {
204                    haveVideo = true;
205                    addSource(impl);
206                    if (!isScrambledFormat(format)) {
207                        mSyncPoints.push();
208                        mSeekSyncPoints = &mSyncPoints.editTop();
209                    }
210                }
211            }
212        }
213
214        if (!haveAudio) {
215            sp impl =
216                (AnotherPacketSource *)mParser->getSource(
217                        ATSParser::AUDIO).get();
218
219            if (impl != NULL) {
220                sp format = impl->getFormat();
221                if (format != NULL) {
222                    haveAudio = true;
223                    addSource(impl);
224                    if (!isScrambledFormat(format)) {
225                        mSyncPoints.push();
226                        if (!haveVideo) {
227                            mSeekSyncPoints = &mSyncPoints.editTop();
228                        }
229                    }
230                }
231            }
232        }
233
234        addSyncPoint_l(mLastSyncEvent);
235        mLastSyncEvent.reset();
236
237        // ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED is returned when the mpeg2ts
238        // is scrambled but we don't have a MediaCas object set. The extraction
239        // will only continue when setMediaCas() is called successfully.
240        if (err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
241            ALOGI("stopped parsing scrambled content, "
242                  "haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
243                    haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
244            return;
245        }
246
247        // Wait only for 2 seconds to detect audio/video streams.
248        if (ALooper::GetNowUs() - startTime > 2000000ll) {
249            break;
250        }
251    }
252
253    off64_t size;
254    if (mDataSource->getSize(&size) == OK && (haveAudio || haveVideo)) {
255        sp impl = haveVideo
256                ? (AnotherPacketSource *)mParser->getSource(
257                        ATSParser::VIDEO).get()
258                : (AnotherPacketSource *)mParser->getSource(
259                        ATSParser::AUDIO).get();
260        size_t prevSyncSize = 1;
261        int64_t durationUs = -1;
262        List durations;
263        // Estimate duration --- stabilize until you get <500ms deviation.
264        while (feedMore() == OK
265                && ALooper::GetNowUs() - startTime <= 2000000ll) {
266            if (mSeekSyncPoints->size() > prevSyncSize) {
267                prevSyncSize = mSeekSyncPoints->size();
268                int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
269                        - mSeekSyncPoints->keyAt(0);
270                off64_t diffOffset = mSeekSyncPoints->valueAt(prevSyncSize - 1)
271                        - mSeekSyncPoints->valueAt(0);
272                int64_t currentDurationUs = size * diffUs / diffOffset;
273                durations.push_back(currentDurationUs);
274                if (durations.size() > 5) {
275                    durations.erase(durations.begin());
276                    int64_t min = *durations.begin();
277                    int64_t max = *durations.begin();
278                    for (auto duration : durations) {
279                        if (min > duration) {
280                            min = duration;
281                        }
282                        if (max < duration) {
283                            max = duration;
284                        }
285                    }
286                    if (max - min < 500 * 1000) {
287                        durationUs = currentDurationUs;
288                        break;
289                    }
290                }
291            }
292        }
293        status_t err;
294        int64_t bufferedDurationUs;
295        bufferedDurationUs = impl->getBufferedDurationUs(&err);
296        if (err == ERROR_END_OF_STREAM) {
297            durationUs = bufferedDurationUs;
298        }
299        if (durationUs > 0) {
300            const sp meta = impl->getFormat();
301            meta->setInt64(kKeyDuration, durationUs);
302            impl->setFormat(meta);
303        } else {
304            estimateDurationsFromTimesUsAtEnd();
305        }
306    }
307
308    ALOGI("haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
309            haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
310 }

184 - 185: 初始化haveAudiohaveVideofalse. 为什么要这样做呢? 原来接下来会去使用feedMore去读取DataSource文件源中的数据到AnotherPacketSource中, 这两个标志位就是标识A/V Track中是否有读到数据的.

189 - 251: 循环的去读取数据直至①feedMore return != OK或者②时间到了2s或者③有A&V数据了, 就退出循环.(另外一个和DRM有关, 我们在这里暂且不管)

  • 191 - 195: 如果已经读取过数据了, 直接将SyncEvnet加入其中, 然后reset, 退出循环;
  • 196 - 212: 使用ATSParsegetSource去获取Video数据到impl中, 并addSourceVector mSourceImpl中去寻找, 如果找到了就啥事不做, 如果没有找到就加入到这个Vector当中去;
  • 214 - 230: 同上, 是对audio数据进行的操作;
  • 248 - 250: 对时间进行控制, 也就是说这个while循环不能执行超过2s. (如果init超过了2s, 我相信体验一定会像这行号一样, 很250吧_);

263 - 306: 简单的说是用两种方式去计算播放的Duration.

  • 264 - 292: 通过计算从feedMore方法中, 加入的SyncEvent点的最后点 - 第一点来计算duration. 然后将这些duration放在一起比较, 当最近的5个duration相差在500ms内的时候, 就算计算完成了; (这是一种)
  • 293 - 306: 通过getBufferedDurationUs或者estimateDurationsFromTimesUsAtEnd来估算Duration.

2.2 MPEG2TSExtractor::feedMore()

      feedMore, 以我的英语水平, 我解释为"吃更多"(偷笑~). 看看他吃了些什么东东.

312 status_t MPEG2TSExtractor::feedMore(bool isInit) {
313    Mutex::Autolock autoLock(mLock);
314
315    uint8_t packet[kTSPacketSize];
316    ssize_t n = mDataSource->readAt(mOffset, packet, kTSPacketSize);
317
318    if (n < (ssize_t)kTSPacketSize) {
319        if (n >= 0) {
320            mParser->signalEOS(ERROR_END_OF_STREAM);
321        }
322        return (n < 0) ? (status_t)n : ERROR_END_OF_STREAM;
323    }
324
325    ATSParser::SyncEvent event(mOffset);
326    mOffset += n;
327    status_t err = mParser->feedTSPacket(packet, kTSPacketSize, &event);
328    if (event.hasReturnedData()) {
329        if (isInit) {
330            mLastSyncEvent = event;
331        } else {
332            addSyncPoint_l(event);
333        }
334    }
335    return err;
336 }

315 - 316: 去DataSource里面读取188个Byte的数据到packet里面;
318 - 323: 判断一下是否eos;
327          : 关键点: 去ATSParser里, 使用feedTSPacket(喂养TS包去咯~).
328 - 334: 根据isInit的状态, 更新下SynvEvent.

3. "ATSParse"闪亮登场

         经过漫长的等待, 我们的ATSParser终于登场了.这位大佬的工作就是专门用来parse program以及其内的stream的. 好的, 让我们来看看他的构造函数:

3.1 ATSParser::ATSParser(uint32_t flags)

1616 ATSParser::ATSParser(uint32_t flags)
1617    : mFlags(flags),
1618      mAbsoluteTimeAnchorUs(-1ll),
1619      mTimeOffsetValid(false),
1620      mTimeOffsetUs(0ll),
1621      mLastRecoveredPTS(-1ll),
1622      mNumTSPacketsParsed(0),
1623      mNumPCRs(0) {
1624    mPSISections.add(0 /* PID */, new PSISection);
1625    mCasManager = new CasManager();
1626 }

1617 - 1623: 简单的对一些标志位, 以及时间戳的标识进行赋值;
1624: 关键点, 将new一个pid = 0PSISection, 并加入mPSISections. 这个在后来的流程中有大作用. 现在暂且不表.(表打我);
1625: new一个CasManager. 这个是干嘛的? 之后在关注. 先看主要流程;

3.2 status_t ATSParser::feedTSPacket(const void *data, size_t size, SyncEvent *event)

      我们来看看是肿么"喂养"TSPacket的吧.

1631 status_t ATSParser::feedTSPacket(const void *data, size_t size,
1632        SyncEvent *event) {
1633    if (size != kTSPacketSize) {
1634        ALOGE("Wrong TS packet size");
1635        return BAD_VALUE;
1636    }
1637
1638    ABitReader br((const uint8_t *)data, kTSPacketSize);
1639    return parseTS(&br, event);
1640 }

1633 - 1636: 判断下kTSPacketSize的大小;
1638: 初试化一个ABitReader br去读取这个容量为188的TS packet;
1639: 走进parseTS;

3.3 status_t ATSParser::parseTS(ABitReader *br, SyncEvent *event)

      
      在正式展开parse TS包工作之前, 我建议再回顾下TS包的组织结构. 在这里, 我就引用其他大神画的图了.TS流格头部如图所示:

MPEG2TSExtractor简析_第1张图片
TS流头部解析图

      在了解了TS头部是如何组织起来的后, 我们来看看具体是如何完成 parseTS工作的, 代码如下所示:

1950 status_t ATSParser::parseTS(ABitReader *br, SyncEvent *event) {
1951    ALOGV("---------------------start parse TS-----------------------");
1952
1953    unsigned sync_byte = br->getBits(8);
1954    if (sync_byte != 0x47u) {
1955        ALOGE("[error] parseTS: return error as sync_byte=0x%x", sync_byte);
1956        return BAD_VALUE;
1957    }
1958
1959    if (br->getBits(1)) {  // transport_error_indicator
1960        // silently ignore.
1961        return OK;
1962    }
1963
1964    unsigned payload_unit_start_indicator = br->getBits(1);
1965    ALOGV("payload_unit_start_indicator = %u", payload_unit_start_indicator);
1966
1967    MY_LOGV("transport_priority = %u", br->getBits(1));
1968
1969    unsigned PID = br->getBits(13);
1970    ALOGV("PID = 0x%04x", PID);
1971
1972    unsigned transport_scrambling_control = br->getBits(2);
1973    ALOGV("transport_scrambling_control = %u", transport_scrambling_control);
1974
1975    unsigned adaptation_field_control = br->getBits(2);
1976    ALOGV("adaptation_field_control = %u", adaptation_field_control);
1977
1978    unsigned continuity_counter = br->getBits(4);
1979    ALOGV("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
1980
1981    // ALOGI("PID = 0x%04x, continuity_counter = %u", PID, continuity_counter);
1982
1983    status_t err = OK;
1984
1985    unsigned random_access_indicator = 0;
1986    if (adaptation_field_control == 2 || adaptation_field_control == 3) {
1987        err = parseAdaptationField(br, PID, &random_access_indicator);
1988    }
1989    if (err == OK) {
1990        if (adaptation_field_control == 1 || adaptation_field_control == 3) {
1991            err = parsePID(br, PID, continuity_counter,
1992                    payload_unit_start_indicator,
1993                    transport_scrambling_control,
1994                    random_access_indicator,
1995                    event);
1996        }
1997    }
1998
1999    ++mNumTSPacketsParsed;
2000
2001    return err;
2002 }

1953 - 1957: 读取8bit, 看下是否是0x47;
1959 - 1962: 如果传输错误, 返回OK. (想了一下, 这样做的后果是, 虽然上面就收到OK, 但是AnohterPacketSource依然是拿不到ABuffer数据的, 所以会继续执行feedMore);
1964 - 1695: parload 起始指示符;
1969 - 1970: 读取13bit, 拿到PID. 这波操作很关键. 这个PID唯一的标识着这个包, 我们可以通过判断PID的值, 获取到这一包TS是什么数据包含其中. 具体的, 下文将具体展开. 这里, 我们只看下PID代表哪些包;

PID取值 PID值使用描述
0x0000 节目关联表(program association table, PAT)
0x0001 条件访问表(conditional access table, CAT)
0x0002 传送流描述表(transport stream description table, TSDT)
0x0003~0x000F 保留
0x0010~0x1FFE 可以分配为network PID, Program map PID, elementary PID, 或其它
0x1FFF 空包(8191)

1972 - 1973: 读取2bit, 标识传输过程中是否加扰;
1975 - 1976: 读取2bit, 标识自适应段控制. 那具体怎么个控制法, 我们来看一张表格;

调整字段值 十进制 描述
00 0 保留
01 1 没有调整字段,仅含有184B长度的有效净荷
10 2 没有有效净荷,仅含有183B长度的调整字段
11 3 0~182B的调整字段后为有效净荷

从表格中, 我们很容易知道两点信息. ①前1个bit, 1代表有调整字段, 反之则没有; ②后1个bit, 1代表有available payload. 这里的信息, 对于接下来的parse 工作是十分重要的.

1978 - 1979: 读取4bit, 标识连续计数器(0 - f, 如果超过f, 则从0开始继续计数);
1986 - 1988: 如果是没有有效净荷,仅含有183B长度的调整字段 || 0~182B的调整字段后为有效净荷 , 也就是说, 这个TS packet中有自适应字段, 那么我们调用parseAdaptationField, 搞搞自适应字段的parse工作;
1990 - 1997: 如果没有出错(err = OK), 那么如果1, 3(有available payload), 我们就开始针对PIDparse数据啦.在此调用的是parsePID;
1999 - 2001: parse的TS packet数量自增, 然后返回parse的结果err.
      接下来, 我们就来看看parseAdaptationFieldparsePID吧.

3.4 status_t ATSParser::parseAdaptationField

1880 status_t ATSParser::parseAdaptationField(
1881        ABitReader *br, unsigned PID, unsigned *random_access_indicator) {
1882    *random_access_indicator = 0;
1883    unsigned adaptation_field_length = br->getBits(8);
1884
1885    if (adaptation_field_length > 0) {
1886        if (adaptation_field_length * 8 > br->numBitsLeft()) {
1887            ALOGV("Adaptation field should be included in a single TS packet.");
1888            return ERROR_MALFORMED;
1889        }
1890
1891        unsigned discontinuity_indicator = br->getBits(1);
1892
1893        if (discontinuity_indicator) {
1894            ALOGV("PID 0x%04x: discontinuity_indicator = 1 (!!!)", PID);
1895        }
1896
1897        *random_access_indicator = br->getBits(1);
1898        if (*random_access_indicator) {
1899            ALOGV("PID 0x%04x: random_access_indicator = 1", PID);
1900        }
1901
1902        unsigned elementary_stream_priority_indicator = br->getBits(1);
1903        if (elementary_stream_priority_indicator) {
1904            ALOGV("PID 0x%04x: elementary_stream_priority_indicator = 1", PID);
1905        }
1906
1907        unsigned PCR_flag = br->getBits(1);
1908
1909        size_t numBitsRead = 4;
1910
1911        if (PCR_flag) {
1912            if (adaptation_field_length * 8 < 52) {
1913                return ERROR_MALFORMED;
1914            }
1915            br->skipBits(4);
1916            uint64_t PCR_base = br->getBits(32);
1917            PCR_base = (PCR_base << 1) | br->getBits(1);
1918
1919            br->skipBits(6);
1920            unsigned PCR_ext = br->getBits(9);
1921
1922            // The number of bytes from the start of the current
1923            // MPEG2 transport stream packet up and including
1924            // the final byte of this PCR_ext field.
1925            size_t byteOffsetFromStartOfTSPacket =
1926                (188 - br->numBitsLeft() / 8);
1927
1928            uint64_t PCR = PCR_base * 300 + PCR_ext;
1929
1930            ALOGV("PID 0x%04x: PCR = 0x%016" PRIx64 " (%.2f)",
1931                  PID, PCR, PCR / 27E6);
1932
1933            // The number of bytes received by this parser up to and
1934            // including the final byte of this PCR_ext field.
1935            uint64_t byteOffsetFromStart =
1936                uint64_t(mNumTSPacketsParsed) * 188 + byteOffsetFromStartOfTSPacket;
1937            //按照PID去更新PCR信息
1938            for (size_t i = 0; i < mPrograms.size(); ++i) {
1939                updatePCR(PID, PCR, byteOffsetFromStart);
1940            }
1941
1942            numBitsRead += 52;
1943        }
1944        //把剩下的无用的bit位跳过处理;
1945        br->skipBits(adaptation_field_length * 8 - numBitsRead);
1946    }
1947    return OK;
1948 }

1883: 读取8bit, 获取自适应字段长度;
1885 - 1889: 如果长度>剩下的长度, 返回ERROR_MALFORMED;
1891: 读取1bit, 非连续指示符;
1897: 读取1bit, 随机读取指示符;
1902: 读取1bit, 基本流优先级指示符;
1907: PCR标志;
1911 - 1946: 处理PCR相关事宜, 小弟关于此部分还没有研究, 暂且跳过;

3.5 status_t ATSParser::parsePID

      代码是在太长了, 不知各位客官是否还记得, 在parseAdaptationField后, 如果err == OK, 那么我们继续进行parsePID的工作.

1778 status_t ATSParser::parsePID(
1779        ABitReader *br, unsigned PID,
1780        unsigned continuity_counter,
1781        unsigned payload_unit_start_indicator,
1782        unsigned transport_scrambling_control,
1783        unsigned random_access_indicator,
1784        SyncEvent *event) {
1785    ssize_t sectionIndex = mPSISections.indexOfKey(PID);
1786
1787    if (sectionIndex >= 0) {
1788        sp section = mPSISections.valueAt(sectionIndex);
1789
1790        if (payload_unit_start_indicator) {
1791            if (!section->isEmpty()) {
1792                ALOGW("parsePID encounters payload_unit_start_indicator when section is not empty");
1793                section->clear();
1794            }
1795
1796            unsigned skip = br->getBits(8);
1797            section->setSkipBytes(skip + 1);  // skip filler bytes + pointer field itself
1798            br->skipBits(skip * 8);
1799        }
1800
1801        if (br->numBitsLeft() % 8 != 0) {
1802            return ERROR_MALFORMED;
1803        }
1804        status_t err = section->append(br->data(), br->numBitsLeft() / 8);
1805
1806        if (err != OK) {
1807            return err;
1808        }
1809
1810        if (!section->isComplete()) {
1811            return OK;
1812        }
1813
1814        if (!section->isCRCOkay()) {
1815            return BAD_VALUE;
1816        }
1817        ABitReader sectionBits(section->data(), section->size());
1818
1819        if (PID == 0) {
1820            parseProgramAssociationTable(§ionBits);
1821        } else {
1822            bool handled = false;
1823            for (size_t i = 0; i < mPrograms.size(); ++i) {
1824                status_t err;
1825                if (!mPrograms.editItemAt(i)->parsePSISection(
1826                            PID, §ionBits, &err)) {
1827                    continue;
1828                }
1829
1830                if (err != OK) {
1831                    return err;
1832                }
1833
1834                handled = true;
1835                break;
1836            }
1837
1838            if (!handled) {
1839                mPSISections.removeItem(PID);
1840                section.clear();
1841            }
1842        }
1843
1844        if (section != NULL) {
1845            section->clear();
1846        }
1847
1848        return OK;
1849    }
1850
1851    bool handled = false;
1852    for (size_t i = 0; i < mPrograms.size(); ++i) {
1853        status_t err;
1854        if (mPrograms.editItemAt(i)->parsePID(
1855                    PID, continuity_counter,
1856                    payload_unit_start_indicator,
1857                    transport_scrambling_control,
1858                    random_access_indicator,
1859                    br, &err, event)) {
1860            if (err != OK) {
1861                return err;
1862            }
1863
1864            handled = true;
1865            break;
1866        }
1867    }
1868
1869    if (!handled) {
1870        handled = mCasManager->parsePID(br, PID);
1871    }
1872
1873    if (!handled) {
1874        ALOGV("PID 0x%04x not handled.", PID);
1875    }
1876
1877    return OK;
1878 }

      首先, 我们去获取到PSISection的index. 继而操作这个PSISection(Program Special Information).不知各位看官是否还记得, 在3.3 parseTS中, 我们有提到MPEG2 TS传输的TS包, 携带两类信息: ①已压缩的A/V(PES)和②与之相关的符号化表(PSI). 这些信息都是通过PID来区别的.
      我们在parse的工作中, 要首先去解析PSI所携带的信息, 然后根据或者的信息, 去解析PES信息.好了, 我们来看看代码实现.

1785: 获取PSISection的index(PSISection被组织在一个KeyedVector > mPSISections;中, Key为PID, Value为sp);

1787 - 1849: 如果index >= 0, 我们就开始进行parse PSI的工作啦.(在ATSParse构造函数中, 我们mPSISections.add(0 /* PID */, new PSISection);. 可见, 如果是在init过程中, 这个index = 0).

  • 1790 - 1799: 如果payload_unit_start_indicator = 1, 表示TS包带有PSI部分的第一个字节,即第一个字节带有指针pointer_field. 所以我们要跳过skip + pointer_field指针所占的8个bit;

  • 1801 - 1803: 如果剩下的bit数不是8的倍数, 返回不符合;

  • 1804: 将剩下的bit位append到PSISection管理的Data中;

  • 1817: new一个sectionBits, 准备开始读取bit位.

  • 1819 - 1820: 重点: 如果PID == 0(Program Association Table, 定义了TS中的所有节目, 是PSI信息表的根节点). 代表当前PSI表为PAT表, 我们要进行parseProgramAssociationTable的工作.

  • 1821 - 1849: 如果PID != 0, 我们通过for循环去处理每个解析出来的program.去调用每个program -> parsePSISection. 如果没有处理到(handle = false), 就去处理掉这些PSISection;

1852 - 1867: 在解析完成后, 我们对于每个Program进行parsePID的工作;

3.6 void ATSParser::parseProgramAssociationTable(ABitReader *br)

      我们在这个方法中, 处理PID == 0x0000的PAT.它的格式如下图:

MPEG2TSExtractor简析_第2张图片
PAT表

      上图中,程序在解析到N环部分的时候,会读取并保存节目列表及其PID。PAT信息在TS流中隔一段时间就会传送,接收机在接收时,以接收PAT表为起始。PAT表列出了TS流中所有的节目列表,以及节目对应的PID值,这个PID值表征的是该节目对应的PMT表的PID值(PMT表稍后说明)。PAT表与PMT的关系如下图。(这一段引用自 TS流基本概念)
MPEG2TSExtractor简析_第3张图片
PAT <-> PMT关系图

      了解到这一步就可以着手于代码了, 小弟这就上代码.

1712 void ATSParser::parseProgramAssociationTable(ABitReader *br) { //简称parsePAT
1713    unsigned table_id = br->getBits(8);
1714    ALOGV("  table_id = %u", table_id);
1715    if (table_id != 0x00u) {
1716        ALOGE("PAT data error!");
1717        return ;
1718    }
1719    unsigned section_syntax_indictor = br->getBits(1);
1720    ALOGV("  section_syntax_indictor = %u", section_syntax_indictor);
1721
1722    br->skipBits(1);  // '0'
1723    MY_LOGV("  reserved = %u", br->getBits(2));
1724
1725    unsigned section_length = br->getBits(12);
1726    ALOGV("  section_length = %u", section_length);
1727
1728    MY_LOGV("  transport_stream_id = %u", br->getBits(16));
1729    MY_LOGV("  reserved = %u", br->getBits(2));
1730    MY_LOGV("  version_number = %u", br->getBits(5));
1731    MY_LOGV("  current_next_indicator = %u", br->getBits(1));
1732    MY_LOGV("  section_number = %u", br->getBits(8));
1733    MY_LOGV("  last_section_number = %u", br->getBits(8));
1734
1735    size_t numProgramBytes = (section_length - 5 /* header */ - 4 /* crc */);
1736
1737    for (size_t i = 0; i < numProgramBytes / 4; ++i) {
1738        unsigned program_number = br->getBits(16);
1739        ALOGV("    program_number = %u", program_number);
1740
1741        MY_LOGV("    reserved = %u", br->getBits(3));
1742
1743        if (program_number == 0) {
1744            MY_LOGV("    network_PID = 0x%04x", br->getBits(13));
1745        } else {
1746            unsigned programMapPID = br->getBits(13);
1747
1748            ALOGV("    program_map_PID = 0x%04x", programMapPID);
1749
1750            bool found = false;
1751            for (size_t index = 0; index < mPrograms.size(); ++index) {
1752                const sp &program = mPrograms.itemAt(index);
1753
1754                if (program->number() == program_number) {
1755                    program->updateProgramMapPID(programMapPID);
1756                    found = true;
1757                    break;
1758                }
1759            }
1760
1761            if (!found) {
1762                mPrograms.push(
1763                        new Program(this, program_number, programMapPID, mLastRecoveredPTS));
1764                if (mSampleAesKeyItem != NULL) {
1765                    mPrograms.top()->signalNewSampleAesKey(mSampleAesKeyItem);
1766                }
1767            }
1768
1769            if (mPSISections.indexOfKey(programMapPID) < 0) {
1770                mPSISections.add(programMapPID, new PSISection);
1771            }
1772        }
1773    }
1774
1775    MY_LOGV("  CRC = 0x%08x", br->getBits(32));
1776 }

1713 - 1718: 读取8bit, 获取table_id. 判断一下table_id == 0x00;
1719 - 1720: 读取1bit, 分段句法指示符;
1722 - 1723: skip '0';
1725 - 1726: 读取12bit, 分段长度;
1735: 计算numProgramBytes = section_length - header的长度(5) - CRC校验所占长度(4);
1737 - 1773: 开始for循环, 从循环条件可以看到, 每次处理4个Byte.

  • 1738 -1739: 读取16bit -> 节目号(program_number);
  • 1743 - 1744: (program_number == 0)代表着这个PSI表为NAT表. 紧接着就去读取13bit -> 网络PID(network_PID);
  • 1746 - 1748: 如果不是program_number != 0, 读取13bit -> 节目映射号(program_map_PID);
  • 1751 - 1759: 根据节目号program_number去节目Vector寻找. 如果找到了, 那么就更新节目号对应的节目ID;
  • 1761 - 1767: 如果没有找到, 那就将当前的program加入到Vector中去;
  • 1769 - 1771: 最后, 如果KeyedVector > mPSISections中没有加入当前的program_map_PID, 那么就加入其中

1775: 读取32bit, 给出最后的CRC校验位;


小结一下: 从代码中可以知道:
①: mPSISections中组织着keyPID, valuesp的keyVector;
②: mPrograms中组织着sp的Vector;
在此方法中维护的这两点, 会在我们在3.5 status_t ATSParser::parsePID中使用得到. 至此, 我们将进入ATSParse的内部类ATSParser::Program去分析在3.5中调用的两个方法: ① parsePSISection; ② parsePID.

4 开启"节目"的大门

      经过长途的跋涉, 我们来到了"Program"游乐园的门口. 闲话少说, 我们构造一张"门票", 看看"门票"代码.

4.1 ATSParser::Program::Program( ATSParser *parser, unsigned programNumber, unsigned programMapPID, int64_t lastRecoveredPTS))

285 ATSParser::Program::Program(
286        ATSParser *parser, unsigned programNumber, unsigned programMapPID,
287        int64_t lastRecoveredPTS)
288    : mParser(parser),
289      mProgramNumber(programNumber),
290      mProgramMapPID(programMapPID),
291      mFirstPTSValid(false),
292      mFirstPTS(0),
293      mLastRecoveredPTS(lastRecoveredPTS) {
294    ALOGV("new program number %u", programNumber);
295 }

288 - 294: 拿到节目号, 节目ID, PTS标志位和PTS, 还有最后恢复PTS. 最后announce出来, 新的program号.
Ps: 哈哈, 门票还是很好拿的说~

4.1

297 bool ATSParser::Program::parsePSISection(
298        unsigned pid, ABitReader *br, status_t *err) {
299    *err = OK;
300
301    if (pid != mProgramMapPID) {
302        return false;
303    }
304
305    *err = parseProgramMap(br);
306
307    return true;
308}

301 - 302: 再次检查传入的pid 是否和当前实例的mProgramMapPID相等;
305: 走parseProgramMap;

4.1.1 status_t ATSParser::Program::parseProgramMap(ABitReader *br)

      "每个简单的方法背后,都有另一个复杂的方法 ^_^ "诚然, 既然parsePSISection这么简单, 那么parseProgramMap一定很复杂咯. 但在此之前, 我们回顾下PMT表的结构, 如下图所示:

MPEG2TSExtractor简析_第4张图片
PMT表解析

      程序在读取N环的时候会读取该节目所有的码流列表及其PID,解析的时候可以根据PID来分离。这N环描述符包括的信息如下图所示。
MPEG2TSExtractor简析_第5张图片
Stream信息图

      节目时钟参考PCR的PID和视频的PID是相等的。由PAT得出所有的节目列表,选定收看的节目后,筛选出等于该节目PID的TS包,就可以得到该节目的所有码流的PID映射表,这样接收机就可以只接收PID等于该节目的码流的TS包即可收看该节目。(这一段引用自TS流基本概念)
现在我们看看其冗长的代码吧.

456 status_t ATSParser::Program::parseProgramMap(ABitReader *br) {
457    unsigned table_id = br->getBits(8);
458    ALOGV("  table_id = %u", table_id);
459    if (table_id != 0x02u) {
460        ALOGE("PMT data error!");
461        return ERROR_MALFORMED;
462    }
463    unsigned section_syntax_indicator = br->getBits(1);
464    ALOGV("  section_syntax_indicator = %u", section_syntax_indicator);
465    if (section_syntax_indicator != 1u) {
466        ALOGE("PMT data error!");
467        return ERROR_MALFORMED;
468    }
469
470    br->skipBits(1);  // '0'
471    MY_LOGV("  reserved = %u", br->getBits(2));
472
473    unsigned section_length = br->getBits(12);
474    ALOGV("  section_length = %u", section_length);
475
476    MY_LOGV("  program_number = %u", br->getBits(16));
477    MY_LOGV("  reserved = %u", br->getBits(2));
478    MY_LOGV("  version_number = %u", br->getBits(5));
479    MY_LOGV("  current_next_indicator = %u", br->getBits(1));
480    MY_LOGV("  section_number = %u", br->getBits(8));
481    MY_LOGV("  last_section_number = %u", br->getBits(8));
482    MY_LOGV("  reserved = %u", br->getBits(3));
483
484    unsigned PCR_PID = br->getBits(13);
485    ALOGV("  PCR_PID = 0x%04x", PCR_PID);
486
487    MY_LOGV("  reserved = %u", br->getBits(4));
488
489    unsigned program_info_length = br->getBits(12);
490    ALOGV("  program_info_length = %u", program_info_length);
491
492    // descriptors
493    CADescriptor programCA;
494    bool hasProgramCA = findCADescriptor(br, program_info_length, &programCA);
495    if (hasProgramCA && !mParser->mCasManager->addProgram(
496            mProgramNumber, programCA)) {
497        return ERROR_MALFORMED;
498    }
499
500    Vector infos;
501
502    // infoBytesRemaining is the number of bytes that make up the
503    // variable length section of ES_infos. It does not include the
504    // final CRC.
505    size_t infoBytesRemaining = section_length - 9 - program_info_length - 4;
506
507    while (infoBytesRemaining >= 5) {
508
509        unsigned streamType = br->getBits(8);
510        ALOGV("    stream_type = 0x%02x", streamType);
511
512        MY_LOGV("    reserved = %u", br->getBits(3));
513
514        unsigned elementaryPID = br->getBits(13);
515        ALOGV("    elementary_PID = 0x%04x", elementaryPID);
516
517        MY_LOGV("    reserved = %u", br->getBits(4));
518
519        unsigned ES_info_length = br->getBits(12);
520        ALOGV("    ES_info_length = %u", ES_info_length);
521
522        CADescriptor streamCA;
523        bool hasStreamCA = findCADescriptor(br, ES_info_length, &streamCA);
524        if (hasStreamCA && !mParser->mCasManager->addStream(
525                mProgramNumber, elementaryPID, streamCA)) {
526            return ERROR_MALFORMED;
527        }
528        StreamInfo info;
529        info.mType = streamType;
530        info.mPID = elementaryPID;
531        info.mCASystemId = hasProgramCA ? programCA.mSystemID :
532                           hasStreamCA ? streamCA.mSystemID  : -1;
533        infos.push(info);
534
535        infoBytesRemaining -= 5 + ES_info_length;
536    }
537
538    if (infoBytesRemaining != 0) {
539        ALOGW("Section data remains unconsumed");
540    }
541    MY_LOGV("  CRC = 0x%08x", br->getBits(32));
542
543    bool PIDsChanged = false;
544    for (size_t i = 0; i < infos.size(); ++i) {
545        StreamInfo &info = infos.editItemAt(i);
546
547        ssize_t index = mStreams.indexOfKey(info.mPID);
548
549        if (index >= 0 && mStreams.editValueAt(index)->type() != info.mType) {
550            ALOGI("uh oh. stream PIDs have changed.");
551            PIDsChanged = true;
552            break;
553        }
554    }
555
556    if (PIDsChanged) {
557#if 0
558        ALOGI("before:");
559        for (size_t i = 0; i < mStreams.size(); ++i) {
560            sp stream = mStreams.editValueAt(i);
561
562            ALOGI("PID 0x%08x => type 0x%02x", stream->pid(), stream->type());
563        }
564
565        ALOGI("after:");
566        for (size_t i = 0; i < infos.size(); ++i) {
567            StreamInfo &info = infos.editItemAt(i);
568
569            ALOGI("PID 0x%08x => type 0x%02x", info.mPID, info.mType);
570        }
571#endif
572
573        // we can recover if number of streams for each type remain the same
574        bool success = switchPIDs(infos);
575
576        if (!success) {
577            ALOGI("Stream PIDs changed and we cannot recover.");
578            return ERROR_MALFORMED;
579        }
580    }
581
582    bool isAddingScrambledStream = false;
583    for (size_t i = 0; i < infos.size(); ++i) {
584        StreamInfo &info = infos.editItemAt(i);
585
586        if (mParser->mCasManager->isCAPid(info.mPID)) {
587            // skip CA streams (EMM/ECM)
588            continue;
589        }
590        ssize_t index = mStreams.indexOfKey(info.mPID);
591
592        if (index < 0) {
593            sp stream = new Stream(
594                    this, info.mPID, info.mType, PCR_PID, info.mCASystemId);
595
596            if (mSampleAesKeyItem != NULL) {
597                stream->signalNewSampleAesKey(mSampleAesKeyItem);
598            }
599
600            isAddingScrambledStream |= info.mCASystemId >= 0;
601            mStreams.add(info.mPID, stream);
602        }
603    }
604
605    if (isAddingScrambledStream) {
606        ALOGI("Receiving scrambled streams without descrambler!");
607        return ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED;
608    }
609    return OK;
610 }

457 - 462: 读取8it -> table_id. 如果table_id != 0x02, 返回畸形的;
473: 读取12bit -> section_length;
489 - 490: 读取12bit -> program_info_length(节目信息长度);
500: 定义一个Vector infos来装当前Program中所带的Stream信息
502 - 505: 根据注释, 我们知道infoBytesRemaining是用来组成ES_Infos"可变长度分段"的Byte数;
507 - 536: 当infoBytesRemaining > 5条件满足的时候, 就进入循环搞事情;

  • 509 - 510: 读取8bit -> streamType(流类型);
  • 514 - 515: 读取13bit -> elementaryPID(基本PID);
  • 519 - 520: 读取12bit -> ES_info_length(ES信息长度);

543 - 554: 使用一个for循环, 去检测stream的stream-> type()是否有变化, 如果有变化, PIDsChanged置位为true, 接下来还要做些处理. 这里要注意下两个变量的类型. ①infos: Vector infos; ②mStreams: KeyedVector > mStreams;

556 - 580: 如果上一步检测同一个PID的Stream的tpye是有变化的.

  • 574: 根据注释以及switchPIDs的源码, 我的得知: 如果当每个type的stream数量相同的时候, 就去更换.
  • 576 - 579: 没有成功, 返回畸形的;

582 - 603: 在刚刚组织出来的infos中寻找, 将没有加入到mStream中的info信息加入其中.


小结一下: 至此, 我们已经将所有的节目(Program), 以及每个节目中的A/V流(Stream)识别出来了. 分别放在了mPrograms和mStream`中, 以便后面使用.

4.2 bool ATSParser::Program::parsePID

310 bool ATSParser::Program::parsePID(
311        unsigned pid, unsigned continuity_counter,
312        unsigned payload_unit_start_indicator,
313        unsigned transport_scrambling_control,
314        unsigned random_access_indicator,
315        ABitReader *br, status_t *err, SyncEvent *event) {
316    *err = OK;
317
318    ssize_t index = mStreams.indexOfKey(pid);
319    if (index < 0) {
320        return false;
321    }
322
323    *err = mStreams.editValueAt(index)->parse(
324            continuity_counter,
325            payload_unit_start_indicator,
326            transport_scrambling_control,
327            random_access_indicator,
328            br, event);
329
330    return true;
331 }

      不知各位看官是否还记得, 在ATSParse::parsePID之中, 我们在完成parsePSISection之后, 我们就要开始执行ATSParser::Program::parsePID了.现在来简单解析一下.
318 - 321: 由传入的pid, 找到本program对应的stream. 并做一下简单的判断, 如果没有找到, 直接返回false.
323 - 328: 接着就直接走到了ATSParser的另外一个内部类ATSParser::Stream, 使用它的成员函数parse去解析每个流的数据.

5. ATSParser::Stream

      在我们找到了PAT -> PMT -> Stream后, 我们在这里就开始解析每个Stream的相关信息. 按照惯例, 我们首先要来看看其构造函数的样子, 代码如下:

5.1 ATSParser::Stream::Stream

706 static const size_t kInitialStreamBufferSize = 192 * 1024;
707
708 ATSParser::Stream::Stream(
709        Program *program,
710        unsigned elementaryPID,
711        unsigned streamType,
712        unsigned PCR_PID,
713        int32_t CA_system_ID)
714    : mProgram(program),
715      mElementaryPID(elementaryPID),
716      mStreamType(streamType),
717      mPCR_PID(PCR_PID),
718      mExpectedContinuityCounter(-1),
719      mPayloadStarted(false),
720      mEOSReached(false),
721      mPrevPTS(0),
722      mQueue(NULL),
723      mScrambled(CA_system_ID >= 0) {
724
725    mSampleEncrypted =
726            mStreamType == STREAMTYPE_H264_ENCRYPTED ||
727            mStreamType == STREAMTYPE_AAC_ENCRYPTED  ||
728            mStreamType == STREAMTYPE_AC3_ENCRYPTED;
729
730    ALOGV("new stream PID 0x%02x, type 0x%02x, scrambled %d, SampleEncrypted: %d",
731            elementaryPID, streamType, mScrambled, mSampleEncrypted);
732
733    uint32_t flags =
734            (isVideo() && mScrambled) ? ElementaryStreamQueue::kFlag_ScrambledData :
735            (mSampleEncrypted) ? ElementaryStreamQueue::kFlag_SampleEncryptedData :
736            0;
737
738    ElementaryStreamQueue::Mode mode = ElementaryStreamQueue::INVALID;
739
740    switch (mStreamType) {
741        case STREAMTYPE_H264:
742        case STREAMTYPE_H264_ENCRYPTED:
743            mode = ElementaryStreamQueue::H264;
744            flags |= (mProgram->parserFlags() & ALIGNED_VIDEO_DATA) ?
745                    ElementaryStreamQueue::kFlag_AlignedData : 0;
746            break;
747
748        case STREAMTYPE_MPEG2_AUDIO_ADTS:
749        case STREAMTYPE_AAC_ENCRYPTED:
750            mode = ElementaryStreamQueue::AAC;
751            break;
752
753        case STREAMTYPE_MPEG1_AUDIO:
754        case STREAMTYPE_MPEG2_AUDIO:
755            mode = ElementaryStreamQueue::MPEG_AUDIO;
756            break;
757
758        case STREAMTYPE_MPEG1_VIDEO:
759        case STREAMTYPE_MPEG2_VIDEO:
760            mode = ElementaryStreamQueue::MPEG_VIDEO;
761            break;
762
763        case STREAMTYPE_MPEG4_VIDEO:
764            mode = ElementaryStreamQueue::MPEG4_VIDEO;
765            break;
766
767        case STREAMTYPE_LPCM_AC3:
768        case STREAMTYPE_AC3:
769        case STREAMTYPE_AC3_ENCRYPTED:
770            mode = ElementaryStreamQueue::AC3;
771            break;
772
773        case STREAMTYPE_METADATA:
774            mode = ElementaryStreamQueue::METADATA;
775            break;
776
777        default:
778            ALOGE("stream PID 0x%02x has invalid stream type 0x%02x",
779                    elementaryPID, streamType);
780            return;
781    }
782
783    mQueue = new ElementaryStreamQueue(mode, flags);
784
785    if (mQueue != NULL) {
786        if (mSampleAesKeyItem != NULL) {
787            mQueue->signalNewSampleAesKey(mSampleAesKeyItem);
788        }
789
790        ensureBufferCapacity(kInitialStreamBufferSize);
791
792        if (mScrambled && (isAudio() || isVideo())) {
793            // Set initial format to scrambled
794            sp meta = new MetaData();
795            meta->setCString(kKeyMIMEType,
796                    isAudio() ? MEDIA_MIMETYPE_AUDIO_SCRAMBLED
797                              : MEDIA_MIMETYPE_VIDEO_SCRAMBLED);
798            // for MediaExtractor.CasInfo
799            meta->setInt32(kKeyCASystemID, CA_system_ID);
800            mSource = new AnotherPacketSource(meta);
801        }
802    }
803 }

      这个构造函数看起来很冗长, 但是实质上没做啥事, 让小弟给各位看官稍加解释.

740 - 781: 根据之前在parseProgramMap中得到streamType, 我们要new一个ElementaryStreamQueue出来. 那ElementaryStreamQueue又是干神马的咧? 这里只能告诉大家是将最终解析出来的数据组织成一个ABuffer, 这个ABuffer是下一层用作解码的单元Buffer(应该是很重要的单元吧).

792 - 801: 如果加了干扰, 并且有A/V, 那么我们就new一个MetaData, 并且把关键字为kKeyMIMEType的媒体类型设置其中. 然后再根据这个meta, 去创建一个AnotherPacketSource出来, 并放入mSource中.

5.2 status_t ATSParser::Stream::parse

855 status_t ATSParser::Stream::parse(
856        unsigned continuity_counter,
857        unsigned payload_unit_start_indicator,
858        unsigned transport_scrambling_control,
859        unsigned random_access_indicator,
860        ABitReader *br, SyncEvent *event) {
861    if (mQueue == NULL) {
862        return OK;
863    }
864
865    if (mExpectedContinuityCounter >= 0
866            && (unsigned)mExpectedContinuityCounter != continuity_counter) {
867        ALOGI("discontinuity on stream pid 0x%04x", mElementaryPID);
868
869        mPayloadStarted = false;
870        mPesStartOffsets.clear();
871        mBuffer->setRange(0, 0);
872        mSubSamples.clear();
873        mExpectedContinuityCounter = -1;
874
875#if 0
876        // Uncomment this if you'd rather see no corruption whatsoever on
877        // screen and suspend updates until we come across another IDR frame.
878
879        if (mStreamType == STREAMTYPE_H264) {
880            ALOGI("clearing video queue");
881            mQueue->clear(true /* clearFormat */);
882        }
883#endif
884
885        if (!payload_unit_start_indicator) {
886            return OK;
887        }
888    }
889
890    mExpectedContinuityCounter = (continuity_counter + 1) & 0x0f;
891
892    if (payload_unit_start_indicator) {
893        off64_t offset = (event != NULL) ? event->getOffset() : 0;
894        if (mPayloadStarted) {
895            // Otherwise we run the danger of receiving the trailing bytes
896            // of a PES packet that we never saw the start of and assuming
897            // we have a a complete PES packet.
898
899            status_t err = flush(event);
900
901            if (err != OK) {
902                ALOGW("Error (%08x) happened while flushing; we simply discard "
903                      "the PES packet and continue.", err);
904            }
905        }
906
907        mPayloadStarted = true;
908        // There should be at most 2 elements in |mPesStartOffsets|.
909        while (mPesStartOffsets.size() >= 2) {
910            mPesStartOffsets.erase(mPesStartOffsets.begin());
911        }
912        mPesStartOffsets.push_back(offset);
913    }
914
915    if (!mPayloadStarted) {
916        return OK;
917    }
918
919    size_t payloadSizeBits = br->numBitsLeft();
920    if (payloadSizeBits % 8 != 0u) {
921        ALOGE("Wrong value");
922        return BAD_VALUE;
923    }
924
925    size_t neededSize = mBuffer->size() + payloadSizeBits / 8;
926    ensureBufferCapacity(neededSize);
927
928    memcpy(mBuffer->data() + mBuffer->size(), br->data(), payloadSizeBits / 8);
929    mBuffer->setRange(0, mBuffer->size() + payloadSizeBits / 8);
930
931    if (mScrambled) {
932        mSubSamples.push_back({payloadSizeBits / 8,
933                 transport_scrambling_control, random_access_indicator});
934    }
935
936    return OK;
937 }

      在看完构造函数以后, 我们来看一看他的parse方法.
865 - 888: 在构造函数中, mExpectedContinuityCounter = -1.所在在刚刚开始parse的时候是不走这个if的;
892 - 913: 如有有"有效载荷单元起始指示符", 则说明当前Parse的TS包内有PES包的第一个字节. (前面有提到过, 如果TS包带有的是PSI数据时, 那么有"有效载荷单元指示符", 代表着这个TS包包含PSI部分的第一个字节);

  • 894 - 905: 重点: 如果当前payload开始处理了(mPayloadStarted = true), 执行flush.(在第一次进入parse方法的时候, 是不进入这个分支的);
  • 907: 标识当前payload开始工作了(mPayloadStarted = true);
  • 909 - 912: 如果mPesStartOffsets维护的List队列中高于两个元素的时候, 将队列头erase (也就是说, 这个列表中, 只维护0 - 1个offset在其中). 然后将最新的offset加入List中;

915 - 917: 如果当前payload还没开始(!mPayloadStarted), return OK;
919 - 923: 获取payloadSizeBits, 并检测其是否是整数Byte;
925 - 926: 计算出我们需要的Buffer的Size, 并调用ensureBufferCapacity, 去判断是否有空间去申请更大的Buffer.
928 - 929: 将br所指向的Data(这个时候, 它指向的是ES数据), 全部copy到mBuffer(ABuffer)后. 然后设置一下mBuffer的有效范围;
931 - 934: 如果有加扰设置, 使用mSubSamples维护下List;

5.4 status_t ATSParser::Stream::flush(SyncEvent *event)

1452 status_t ATSParser::Stream::flush(SyncEvent *event) {
1453    if (mBuffer == NULL || mBuffer->size() == 0) {
1454        return OK;
1455    }
1456
1457    ALOGV("flushing stream 0x%04x size = %zu", mElementaryPID, mBuffer->size());
1458
1459    status_t err = OK;
1460    if (mScrambled) {
1461        err = flushScrambled(event);
1462        mSubSamples.clear();
1463    } else {
1464        ABitReader br(mBuffer->data(), mBuffer->size());
1465        err = parsePES(&br, event);
1466    }
1467
1468    mBuffer->setRange(0, 0);
1469
1470    return err;
1471 }

      在parse方法中, 我们在mPayloadStart == true的时候, 会调用这个方法去"冲刷"buffer.
1453 - 1455: 判断mBuffer是否可操作;
1460 - 1462: 如果在前面的parse工作中, 发现这个TS包是有mScrambled标识的, 那么走flushScrambled (在这里先不讨论这个方法);
1463 - 1466: 重点: 初始化一个ABitReader去读取组织好的一个ABuffer. 然后走parsePES;
1468: 将当前handle的ABuffer的有效区域设置为(0, 0)(也就是说不可操作了);

5.5 ATSParser::Stream::parsePES

      哈哈, 我们终于走到parsePES了. 终于可以看到究竟是如何处理ES数据包了!别急, 在看冗长的代码前, 我们先回顾来PES的结构表.

标识名 bit 描述
pes start code 24 开始码,固定为0x000001
stream id 8 音频取值(0xc0-0xdf),通常为0xc0 <-> 视频取值(0xe0-0xef),通常为0xe0
pes packet length 16 后面pes数据的长度, 0表示长度不限制, 只有视频数据长度会超过0xffff
flag 8 通常取值0x80,表示数据不加密、无优先级、备份的数据
flag 8 取值0x80表示只含有pts,取值0xc0表示含有pts和dts
pes data length 8 后面数据的长度,取值510
pts 33 presentation time stamp
dts 33 decode time stamp

复习完这个表, 我们就可以进入代码的海洋了(这个parsePES方法真的好长o(╥﹏╥)o).

1037 status_t ATSParser::Stream::parsePES(ABitReader *br, SyncEvent *event) {
1038    const uint8_t *basePtr = br->data();
1039
1040    unsigned packet_startcode_prefix = br->getBits(24);
1041
1042    ALOGV("packet_startcode_prefix = 0x%08x", packet_startcode_prefix);
1043
1044    if (packet_startcode_prefix != 1) {
1045        ALOGV("Supposedly payload_unit_start=1 unit does not start "
1046             "with startcode.");
1047
1048        return ERROR_MALFORMED;
1049    }
1050
1051    unsigned stream_id = br->getBits(8);
1052    ALOGV("stream_id = 0x%02x", stream_id);
1053
1054    unsigned PES_packet_length = br->getBits(16);
1055    ALOGV("PES_packet_length = %u", PES_packet_length);
1056
1057    if (stream_id != 0xbc  // program_stream_map
1058            && stream_id != 0xbe  // padding_stream
1059            && stream_id != 0xbf  // private_stream_2
1060            && stream_id != 0xf0  // ECM
1061            && stream_id != 0xf1  // EMM
1062            && stream_id != 0xff  // program_stream_directory
1063            && stream_id != 0xf2  // DSMCC
1064            && stream_id != 0xf8) {  // H.222.1 type E
1065        if (br->getBits(2) != 2u) {
1066            return ERROR_MALFORMED;
1067        }
1068
1069        unsigned PES_scrambling_control = br->getBits(2);
1070        ALOGV("PES_scrambling_control = %u", PES_scrambling_control);
1071
1072        MY_LOGV("PES_priority = %u", br->getBits(1));
1073        MY_LOGV("data_alignment_indicator = %u", br->getBits(1));
1074        MY_LOGV("copyright = %u", br->getBits(1));
1075        MY_LOGV("original_or_copy = %u", br->getBits(1));
1076
1077        unsigned PTS_DTS_flags = br->getBits(2);
1078        ALOGV("PTS_DTS_flags = %u", PTS_DTS_flags);
1079
1080        unsigned ESCR_flag = br->getBits(1);
1081        ALOGV("ESCR_flag = %u", ESCR_flag);
1082
1083        unsigned ES_rate_flag = br->getBits(1);
1084        ALOGV("ES_rate_flag = %u", ES_rate_flag);
1085
1086        unsigned DSM_trick_mode_flag = br->getBits(1);
1087        ALOGV("DSM_trick_mode_flag = %u", DSM_trick_mode_flag);
1088
1089        unsigned additional_copy_info_flag = br->getBits(1);
1090        ALOGV("additional_copy_info_flag = %u", additional_copy_info_flag);
1091
1092        MY_LOGV("PES_CRC_flag = %u", br->getBits(1));
1093        MY_LOGV("PES_extension_flag = %u", br->getBits(1));
1094
1095        unsigned PES_header_data_length = br->getBits(8);
1096        ALOGV("PES_header_data_length = %u", PES_header_data_length);
1097
1098        unsigned optional_bytes_remaining = PES_header_data_length;
1099
1100        uint64_t PTS = 0, DTS = 0;
1101
1102        if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
1103            if (optional_bytes_remaining < 5u) {
1104                return ERROR_MALFORMED;
1105            }
1106
1107            if (br->getBits(4) != PTS_DTS_flags) {
1108                return ERROR_MALFORMED;
1109            }
1110            PTS = ((uint64_t)br->getBits(3)) << 30;
1111            if (br->getBits(1) != 1u) {
1112                return ERROR_MALFORMED;
1113            }
1114            PTS |= ((uint64_t)br->getBits(15)) << 15;
1115            if (br->getBits(1) != 1u) {
1116                return ERROR_MALFORMED;
1117            }
1118            PTS |= br->getBits(15);
1119            if (br->getBits(1) != 1u) {
1120                return ERROR_MALFORMED;
1121            }
1122
1123            ALOGV("PTS = 0x%016" PRIx64 " (%.2f)", PTS, PTS / 90000.0);
1124
1125            optional_bytes_remaining -= 5;
1126
1127            if (PTS_DTS_flags == 3) {
1128                if (optional_bytes_remaining < 5u) {
1129                    return ERROR_MALFORMED;
1130                }
1131
1132                if (br->getBits(4) != 1u) {
1133                    return ERROR_MALFORMED;
1134                }
1135
1136                DTS = ((uint64_t)br->getBits(3)) << 30;
1137                if (br->getBits(1) != 1u) {
1138                    return ERROR_MALFORMED;
1139                }
1140                DTS |= ((uint64_t)br->getBits(15)) << 15;
1141                if (br->getBits(1) != 1u) {
1142                    return ERROR_MALFORMED;
1143                }
1144                DTS |= br->getBits(15);
1145                if (br->getBits(1) != 1u) {
1146                    return ERROR_MALFORMED;
1147                }
1148
1149                ALOGV("DTS = %" PRIu64, DTS);
1150
1151                optional_bytes_remaining -= 5;
1152            }
1153        }
1154
1155        if (ESCR_flag) {
1156            if (optional_bytes_remaining < 6u) {
1157                return ERROR_MALFORMED;
1158            }
1159
1160            br->getBits(2);
1161
1162            uint64_t ESCR = ((uint64_t)br->getBits(3)) << 30;
1163            if (br->getBits(1) != 1u) {
1164                return ERROR_MALFORMED;
1165            }
1166            ESCR |= ((uint64_t)br->getBits(15)) << 15;
1167            if (br->getBits(1) != 1u) {
1168                return ERROR_MALFORMED;
1169            }
1170            ESCR |= br->getBits(15);
1171            if (br->getBits(1) != 1u) {
1172                return ERROR_MALFORMED;
1173            }
1174
1175            ALOGV("ESCR = %" PRIu64, ESCR);
1176            MY_LOGV("ESCR_extension = %u", br->getBits(9));
1177
1178            if (br->getBits(1) != 1u) {
1179                return ERROR_MALFORMED;
1180            }
1181
1182            optional_bytes_remaining -= 6;
1183        }
1184
1185        if (ES_rate_flag) {
1186            if (optional_bytes_remaining < 3u) {
1187                return ERROR_MALFORMED;
1188            }
1189
1190            if (br->getBits(1) != 1u) {
1191                return ERROR_MALFORMED;
1192            }
1193            MY_LOGV("ES_rate = %u", br->getBits(22));
1194            if (br->getBits(1) != 1u) {
1195                return ERROR_MALFORMED;
1196            }
1197
1198            optional_bytes_remaining -= 3;
1199        }
1200
1201        br->skipBits(optional_bytes_remaining * 8);
1202
1203        // ES data follows.
1204        int32_t pesOffset = br->data() - basePtr;
1205
1206        if (PES_packet_length != 0) {
1207            if (PES_packet_length < PES_header_data_length + 3) {
1208                return ERROR_MALFORMED;
1209            }
1210
1211            unsigned dataLength =
1212                PES_packet_length - 3 - PES_header_data_length;
1213
1214            if (br->numBitsLeft() < dataLength * 8) {
1215                ALOGE("PES packet does not carry enough data to contain "
1216                     "payload. (numBitsLeft = %zu, required = %u)",
1217                     br->numBitsLeft(), dataLength * 8);
1218
1219                return ERROR_MALFORMED;
1220            }
1221
1222            ALOGV("There's %u bytes of payload, PES_packet_length=%u, offset=%d",
1223                    dataLength, PES_packet_length, pesOffset);
1224
1225            onPayloadData(
1226                    PTS_DTS_flags, PTS, DTS, PES_scrambling_control,
1227                    br->data(), dataLength, pesOffset, event);
1228
1229            br->skipBits(dataLength * 8);
1230        } else {
1231            onPayloadData(
1232                    PTS_DTS_flags, PTS, DTS, PES_scrambling_control,
1233                    br->data(), br->numBitsLeft() / 8, pesOffset, event);
1234
1235            size_t payloadSizeBits = br->numBitsLeft();
1236            if (payloadSizeBits % 8 != 0u) {
1237                return ERROR_MALFORMED;
1238            }
1239
1240            ALOGV("There's %zu bytes of payload, offset=%d",
1241                    payloadSizeBits / 8, pesOffset);
1242        }
1243    } else if (stream_id == 0xbe) {  // padding_stream
1244        if (PES_packet_length == 0u) {
1245            return ERROR_MALFORMED;
1246        }
1247        br->skipBits(PES_packet_length * 8);
1248    } else {
1249        if (PES_packet_length == 0u) {
1250            return ERROR_MALFORMED;
1251        }
1252        br->skipBits(PES_packet_length * 8);
1253    }
1254
1255    return OK;
1256 }

1040 - 1049 : 读取24bit -> packet_startcode_prefix (pes开始的前缀码). 如果前缀码不为1, 直接返回畸形的;
1051 - 1052: 读取8bit -> stream_id;
1054 - 1055: 读取16bit -> PES包长度(PES_packet_length);
1057 - 1242: 如果stream_id 不为代码中列出的类型, 进行如下操作:

  • 1065 - 1067: 读取2bit, 如果不为2, 则返回畸形;

  • 1069 - 1096: 陆续parse出一些信息; 其中比较有用的是PES_header_data_length并存入optional_bytes_remaining变量;

  • 1100 - 1153: 计算PTS和DTS, optional_bytes_remaining -= 5(这说明, PTS/DTS段各占用了5Byte);

  • 1155 - 1183: 如ESCR_flag == true, 就进行对ESCR的操作, optional_bytes_remaining -= 6(这说明, ESCR_flag 段占用了6Byte);

  • 1185 - 1199: 如ES_rate_flag == true, 进行对应的操作, optional_bytes_remaining -= 3(这说明, ES_rate_flag 段占用了3Byte);

  • 1201: 跳过剩余的optional_bytes_remaining;

  • 1203 - 1204: 重点: 我们即将开始看到ES Data的操作了. 计算当前从PES开始到目前为止的Offset, 放入pesOffset中;

  • 1206 - 1229: 如果PES_packet_length不为0.

    • 1207 - 1209: 如果PES_packet_length < PES_header_data_length + 3, 返回"畸形";
    • 1211 - 1212: 计算dataLength;
    • 1214 - 1220: 如果剩下的bit数 < dataLength * 8, 返回"畸形的";
    • 1225 - 1228: 重点: 走进onPayloadData, 去将我们得到的payload信息放入ESQueue管理的ABuffer中;
  • 如果PES_packet_length是其他情况.;

    • 1231 - 1233: 直接调用onPayloadData;
    • 1235 - 1238: 计算payloadSizeBits, 如果不是整数Byte, 返回"畸形的";

1243 - 1247: 如果stream_id == 0xbe(填充的stream). 那么如果PES长度为0 , 直接返回畸形. 否则, 就skip掉这个PES包;
1248 - 1253: 最后stream_id均不属于上述几种的话, 如果PES长度为0 , 直接返回畸形. 否则, 就skip掉这个PES包;

5.6 ATSParser::Stream::onPayloadData

1473 void ATSParser::Stream::onPayloadData(
1474        unsigned PTS_DTS_flags, uint64_t PTS, uint64_t /* DTS */,
1475        unsigned PES_scrambling_control,
1476        const uint8_t *data, size_t size,
1477        int32_t payloadOffset, SyncEvent *event) {
1478#if 0
1479    ALOGI("payload streamType 0x%02x, PTS = 0x%016llx, dPTS = %lld",
1480          mStreamType,
1481          PTS,
1482          (int64_t)PTS - mPrevPTS);
1483    mPrevPTS = PTS;
1484#endif
1485
1486    ALOGV("onPayloadData mStreamType=0x%02x size: %zu", mStreamType, size);
1487
1488    int64_t timeUs = 0ll;  // no presentation timestamp available.
1489    if (PTS_DTS_flags == 2 || PTS_DTS_flags == 3) {
1490        timeUs = mProgram->convertPTSToTimestamp(PTS);
1491    }
1492
1493    status_t err = mQueue->appendData(
1494            data, size, timeUs, payloadOffset, PES_scrambling_control);
1495
1496    if (mEOSReached) {
1497        mQueue->signalEOS();
1498    }
1499
1500    if (err != OK) {
1501        return;
1502    }
1503
1504    sp accessUnit;
1505    bool found = false;
1506    while ((accessUnit = mQueue->dequeueAccessUnit()) != NULL) {
1507        if (mSource == NULL) {
1508            sp meta = mQueue->getFormat();
1509
1510            if (meta != NULL) {
1511                ALOGV("Stream PID 0x%08x of type 0x%02x now has data.",
1512                     mElementaryPID, mStreamType);
1513
1514                const char *mime;
1515                if (meta->findCString(kKeyMIMEType, &mime)
1516                        && !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC)) {
1517                    int32_t sync = 0;
1518                    if (!accessUnit->meta()->findInt32("isSync", &sync) || !sync) {
1519                        continue;
1520                    }
1521                }
1522                mSource = new AnotherPacketSource(meta);
1523                mSource->queueAccessUnit(accessUnit);
1524                ALOGV("onPayloadData: created AnotherPacketSource PID 0x%08x of type 0x%02x",
1525                        mElementaryPID, mStreamType);
1526            }
1527        } else if (mQueue->getFormat() != NULL) {
1528            // After a discontinuity we invalidate the queue's format
1529            // and won't enqueue any access units to the source until
1530            // the queue has reestablished the new format.
1531
1532            if (mSource->getFormat() == NULL) {
1533                mSource->setFormat(mQueue->getFormat());
1534            }
1535            mSource->queueAccessUnit(accessUnit);
1536        }
1537
1538        // Every access unit has a pesStartOffset queued in |mPesStartOffsets|.
1539        off64_t pesStartOffset = -1;
1540        if (!mPesStartOffsets.empty()) {
1541            pesStartOffset = *mPesStartOffsets.begin();
1542            mPesStartOffsets.erase(mPesStartOffsets.begin());
1543        }
1544
1545        if (pesStartOffset >= 0 && (event != NULL) && !found && mQueue->getFormat() != NULL) {
1546            int32_t sync = 0;
1547            if (accessUnit->meta()->findInt32("isSync", &sync) && sync) {
1548                int64_t timeUs;
1549                if (accessUnit->meta()->findInt64("timeUs", &timeUs)) {
1550                    found = true;
1551                    event->init(pesStartOffset, mSource, timeUs, getSourceType());
1552                }
1553            }
1554        }
1555    }
1556 }

      这应该是本文中要讲解的Stream的最后一个方法了吧, 我们来分析一下.
1488 - 1491: 如果no presentation timestamp available. 那么, 就去看PTS_DTS_flags. 如果符合条件, 使用方法convertPTSToTimestamp放入timeUS中;
**1493 - 1494: 重点: ** 调用ElementaryStreamQueue类的appendData方法 (这个方法, 我们会在接下来讲解);
1496 - 1502: 判断下是否EOSerr是否OK;
1506 - 1555: 如果accessUnitmQueue->dequeueAccessUnit()获取到的ABuffer不为空, 进入循环;

  • 1510 - 1526: 如果当前Stream的AnohterPacketSource == NULL
    • 1508 - 1526: 从mQueue获取`MetaData, 如果获取到的不为空:
      • 1514 - 1521: 检查kKeyMIMEType是否为MEDIA_MIMETYPE_VIDEO_AVC.;
        • 如果是的, 并且没有找到isSync标识(非同步), 就继续去做dequeueAccessUnit;
  • 1527 - 1536: 如果此时有了AnotherPacketSouce, 并且能从ElementaryStreamQueue获取到MetaData.
    • 1532 - 1533: 保证是设置有MetaData的;
    • 1535: 将accessUnit加入到AnotherPacketSouce维护的队列之中;
  • 1538 - 1554: 对mPesStartOffsets这个List进行维护;

6 ElementaryStreamQueue

      我们一路跋山涉水, 终于来到了终点站ElementaryStreamQueue(此后, 我将根据其所在的文件名, 简写为ESQueue). 惯例惯例~我们来看看其构造函数吧.

6.1 ElementaryStreamQueue::ElementaryStreamQueue

41 ElementaryStreamQueue::ElementaryStreamQueue(Mode mode, uint32_t flags)
42    : mMode(mode),
43      mFlags(flags),
44      mEOSReached(false),
45      mCASystemId(0),
46      mAUIndex(0) {
47
48    ALOGV("ElementaryStreamQueue(%p) mode %x  flags %x  isScrambled %d  isSampleEncrypted %d",
49            this, mode, flags, isScrambled(), isSampleEncrypted());
50
51    // Create the decryptor anyway since we don't know the use-case unless key is provided
52    // Won't decrypt if key info not available (e.g., scanner/extractor just parsing ts files)
53    mSampleDecryptor = isSampleEncrypted() ? new HlsSampleDecryptor : NULL;
54 }

      (⊙o⊙)…貌似没什么好说的, 好吧, 暂且就先搁这儿吧, 以后有更深刻的理解了再回来补充. 回到正题, 我们赶紧去看看appendData以及dequeueAccessUnit

6.2 status_t ElementaryStreamQueue::appendData

274 status_t ElementaryStreamQueue::appendData(
275        const void *data, size_t size, int64_t timeUs,
276        int32_t payloadOffset, uint32_t pesScramblingControl) {
277
278    if (mEOSReached) {
279        ALOGE("appending data after EOS");
280        return ERROR_MALFORMED;
281    }
282    if (mBuffer == NULL || mBuffer->size() == 0) {
283        switch (mMode) {
284            case H264:
285            case MPEG_VIDEO:
286            {
287#if 0
288                if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
289                    return ERROR_MALFORMED;
290                }
291#else
292                uint8_t *ptr = (uint8_t *)data;
293
294                ssize_t startOffset = -1;
295                for (size_t i = 0; i + 2 < size; ++i) {
296                    if (!memcmp("\x00\x00\x01", &ptr[i], 3)) {
297                        startOffset = i;
298                        break;
299                    }
300                }
301
302                if (startOffset < 0) {
303                    return ERROR_MALFORMED;
304                }
305
306                if (mFormat == NULL && startOffset > 0) {
307                    ALOGI("found something resembling an H.264/MPEG syncword "
308                          "at offset %zd",
309                          startOffset);
310                }
311
312                data = &ptr[startOffset];
313                size -= startOffset;
314#endif
315                break;
316            }
317
318            case MPEG4_VIDEO:
319            {
320#if 0
321                if (size < 3 || memcmp("\x00\x00\x01", data, 3)) {
322                    return ERROR_MALFORMED;
323                }
324#else
325                uint8_t *ptr = (uint8_t *)data;
326
327                ssize_t startOffset = -1;
328                for (size_t i = 0; i + 2 < size; ++i) {
329                    if (!memcmp("\x00\x00\x01", &ptr[i], 3)) {
330                        startOffset = i;
331                        break;
332                    }
333                }
334
335                if (startOffset < 0) {
336                    return ERROR_MALFORMED;
337                }
338
339                if (startOffset > 0) {
340                    ALOGI("found something resembling an H.264/MPEG syncword "
341                          "at offset %zd",
342                          startOffset);
343                }
344
345                data = &ptr[startOffset];
346                size -= startOffset;
347#endif
348                break;
349            }
350
351            case AAC:
352            {
353                uint8_t *ptr = (uint8_t *)data;
354
355#if 0
356                if (size < 2 || ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
357                    return ERROR_MALFORMED;
358                }
359#else
360                ssize_t startOffset = -1;
361                size_t frameLength;
362                for (size_t i = 0; i < size; ++i) {
363                    if (IsSeeminglyValidADTSHeader(
364                            &ptr[i], size - i, &frameLength)) {
365                        startOffset = i;
366                        break;
367                    }
368                }
369
370                if (startOffset < 0) {
371                    return ERROR_MALFORMED;
372                }
373
374                if (startOffset > 0) {
375                    ALOGI("found something resembling an AAC syncword at "
376                          "offset %zd",
377                          startOffset);
378                }
379
380                if (frameLength != size - startOffset) {
381                    ALOGV("First ADTS AAC frame length is %zd bytes, "
382                          "while the buffer size is %zd bytes.",
383                          frameLength, size - startOffset);
384                }
385
386                data = &ptr[startOffset];
387                size -= startOffset;
388#endif
389                break;
390            }
391
392            case AC3:
393            {
394                uint8_t *ptr = (uint8_t *)data;
395
396                ssize_t startOffset = -1;
397                for (size_t i = 0; i < size; ++i) {
398                    if (IsSeeminglyValidAC3Header(&ptr[i], size - i)) {
399                        startOffset = i;
400                        break;
401                    }
402                }
403
404                if (startOffset < 0) {
405                    return ERROR_MALFORMED;
406                }
407
408                if (startOffset > 0) {
409                    ALOGI("found something resembling an AC3 syncword at "
410                          "offset %zd",
411                          startOffset);
412                }
413
414                data = &ptr[startOffset];
415                size -= startOffset;
416                break;
417            }
418
419            case MPEG_AUDIO:
420            {
421                uint8_t *ptr = (uint8_t *)data;
422
423                ssize_t startOffset = -1;
424                for (size_t i = 0; i < size; ++i) {
425                    if (IsSeeminglyValidMPEGAudioHeader(&ptr[i], size - i)) {
426                        startOffset = i;
427                        break;
428                    }
429                }
430
431                if (startOffset < 0) {
432                    return ERROR_MALFORMED;
433                }
434
435                if (startOffset > 0) {
436                    ALOGI("found something resembling an MPEG audio "
437                          "syncword at offset %zd",
438                          startOffset);
439                }
440
441                data = &ptr[startOffset];
442                size -= startOffset;
443                break;
444            }
445
446            case PCM_AUDIO:
447            case METADATA:
448            {
449                break;
450            }
451
452            default:
453                ALOGE("Unknown mode: %d", mMode);
454                return ERROR_MALFORMED;
455        }
456    }
457
458    size_t neededSize = (mBuffer == NULL ? 0 : mBuffer->size()) + size;
459    if (mBuffer == NULL || neededSize > mBuffer->capacity()) {
460        neededSize = (neededSize + 65535) & ~65535;
461
462        ALOGV("resizing buffer to size %zu", neededSize);
463
464        sp buffer = new ABuffer(neededSize);
465        if (mBuffer != NULL) {
466            memcpy(buffer->data(), mBuffer->data(), mBuffer->size());
467            buffer->setRange(0, mBuffer->size());
468        } else {
469            buffer->setRange(0, 0);
470        }
471
472        mBuffer = buffer;
473    }
474
475    memcpy(mBuffer->data() + mBuffer->size(), data, size);
476    mBuffer->setRange(0, mBuffer->size() + size);
477
478    RangeInfo info;
479    info.mLength = size;
480    info.mTimestampUs = timeUs;
481    info.mPesOffset = payloadOffset;
482    info.mPesScramblingControl = pesScramblingControl;
483    mRangeInfos.push_back(info);
484
485#if 0
486    if (mMode == AAC) {
487        ALOGI("size = %zu, timeUs = %.2f secs", size, timeUs / 1E6);
488        hexdump(data, size);
489    }
490#endif
491
492    return OK;
493 }

      看似冗长, 其实是case过多的缘故, 来简单梳理下.
278 - 281: 判断下EOS;
282 - 456: 如果传入的ABuffer判断为有效的话(mBuffer == NULL || mBuffer->size() == 0), 根据传入的mMode(根据stream type定义的), 组织各自类型的结构.
458 - 476: 通过计算neededSize, 来重新调整ESQueue所维护的mBuffer的大小;
478 - 483: 维护RangeInfo(和pes有关);

6.3 sp ElementaryStreamQueue::dequeueAccessUnit()

616 sp ElementaryStreamQueue::dequeueAccessUnit() {
617    if ((mFlags & kFlag_AlignedData) && mMode == H264 && !isScrambled()) {
618        if (mRangeInfos.empty()) {
619            return NULL;
620        }
621
622        RangeInfo info = *mRangeInfos.begin();
623        mRangeInfos.erase(mRangeInfos.begin());
624
625        sp accessUnit = new ABuffer(info.mLength);
626        memcpy(accessUnit->data(), mBuffer->data(), info.mLength);
627        accessUnit->meta()->setInt64("timeUs", info.mTimestampUs);
628
629        memmove(mBuffer->data(),
630                mBuffer->data() + info.mLength,
631                mBuffer->size() - info.mLength);
632
633        mBuffer->setRange(0, mBuffer->size() - info.mLength);
634
635        if (mFormat == NULL) {
636            mFormat = MakeAVCCodecSpecificData(accessUnit);
637        }
638
639        return accessUnit;
640    }
641
642    switch (mMode) {
643        case H264:
644            return dequeueAccessUnitH264();
645        case AAC:
646            return dequeueAccessUnitAAC();
647        case AC3:
648            return dequeueAccessUnitAC3();
649        case MPEG_VIDEO:
650            return dequeueAccessUnitMPEGVideo();
651        case MPEG4_VIDEO:
652            return dequeueAccessUnitMPEG4Video();
653        case PCM_AUDIO:
654            return dequeueAccessUnitPCMAudio();
655        case METADATA:
656            return dequeueAccessUnitMetadata();
657        default:
658            if (mMode != MPEG_AUDIO) {
659                ALOGE("Unknown mode");
660                return NULL;
661            }
662            return dequeueAccessUnitMPEGAudio();
663    }
664 }

617 - 640: 如果①. 传入的mFlagskFlag_AlignedData(append到queue中的Data是在边界的). 并且②. 是H264的Video stream. 并且③. 没有加扰. 满足以上3个条件, 就进入这个分支.

642 - 663: 根据mMode, 分别调用不同stream type的dequeueAccessUnitXXX;


      至此, MPEG2TSExtractor全篇结束. 虽然写的很杂乱, 但是至少是从上到下走了一遍Flow. 如果之后还有更深层的理解, 我再回来慢慢精化.
      这篇应该是年前最后一篇文章了吧. 回顾2017, 惊喜/ 兴奋/ 沮丧/ 悲伤五味杂陈. 不过, 无论如何, 总归是佛系过来了, 2018旺旺旺来了, 好运还会远吗? 不会, 它时刻等待着有准备的人去抓住它.
      向2017说声走好, 向2018说声我来了~

你可能感兴趣的:(MPEG2TSExtractor简析)