TSPacketizer.cpp revision c6920dfdca378a168a2168f4a64d21af4d37d539
1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "TSPacketizer"
19#include <utils/Log.h>
20
21#include "TSPacketizer.h"
22#include "include/avc_utils.h"
23
24#include <media/stagefright/foundation/ABuffer.h>
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/AMessage.h>
27#include <media/stagefright/foundation/hexdump.h>
28#include <media/stagefright/MediaDefs.h>
29#include <media/stagefright/MediaErrors.h>
30
31#include <arpa/inet.h>
32
33namespace android {
34
35struct TSPacketizer::Track : public RefBase {
36    Track(const sp<AMessage> &format,
37          unsigned PID, unsigned streamType, unsigned streamID);
38
39    unsigned PID() const;
40    unsigned streamType() const;
41    unsigned streamID() const;
42
43    // Returns the previous value.
44    unsigned incrementContinuityCounter();
45
46    bool isAudio() const;
47    bool isVideo() const;
48
49    bool isH264() const;
50    bool lacksADTSHeader() const;
51
52    sp<ABuffer> prependCSD(const sp<ABuffer> &accessUnit) const;
53    sp<ABuffer> prependADTSHeader(const sp<ABuffer> &accessUnit) const;
54
55protected:
56    virtual ~Track();
57
58private:
59    sp<AMessage> mFormat;
60
61    unsigned mPID;
62    unsigned mStreamType;
63    unsigned mStreamID;
64    unsigned mContinuityCounter;
65
66    AString mMIME;
67    Vector<sp<ABuffer> > mCSD;
68
69    bool mAudioLacksATDSHeaders;
70
71    DISALLOW_EVIL_CONSTRUCTORS(Track);
72};
73
74TSPacketizer::Track::Track(
75        const sp<AMessage> &format,
76        unsigned PID, unsigned streamType, unsigned streamID)
77    : mFormat(format),
78      mPID(PID),
79      mStreamType(streamType),
80      mStreamID(streamID),
81      mContinuityCounter(0),
82      mAudioLacksATDSHeaders(false) {
83    CHECK(format->findString("mime", &mMIME));
84
85    if (!strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)
86            || !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
87        for (size_t i = 0;; ++i) {
88            sp<ABuffer> csd;
89            if (!format->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) {
90                break;
91            }
92
93            mCSD.push(csd);
94        }
95
96        if (!strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
97            int32_t isADTS;
98            if (!mFormat->findInt32("is-adts", &isADTS) || isADTS == 0) {
99                mAudioLacksATDSHeaders = true;
100            }
101        }
102    }
103}
104
105TSPacketizer::Track::~Track() {
106}
107
108unsigned TSPacketizer::Track::PID() const {
109    return mPID;
110}
111
112unsigned TSPacketizer::Track::streamType() const {
113    return mStreamType;
114}
115
116unsigned TSPacketizer::Track::streamID() const {
117    return mStreamID;
118}
119
120unsigned TSPacketizer::Track::incrementContinuityCounter() {
121    unsigned prevCounter = mContinuityCounter;
122
123    if (++mContinuityCounter == 16) {
124        mContinuityCounter = 0;
125    }
126
127    return prevCounter;
128}
129
130bool TSPacketizer::Track::isAudio() const {
131    return !strncasecmp("audio/", mMIME.c_str(), 6);
132}
133
134bool TSPacketizer::Track::isVideo() const {
135    return !strncasecmp("video/", mMIME.c_str(), 6);
136}
137
138bool TSPacketizer::Track::isH264() const {
139    return !strcasecmp(mMIME.c_str(), MEDIA_MIMETYPE_VIDEO_AVC);
140}
141
142bool TSPacketizer::Track::lacksADTSHeader() const {
143    return mAudioLacksATDSHeaders;
144}
145
146sp<ABuffer> TSPacketizer::Track::prependCSD(
147        const sp<ABuffer> &accessUnit) const {
148    size_t size = 0;
149    for (size_t i = 0; i < mCSD.size(); ++i) {
150        size += mCSD.itemAt(i)->size();
151    }
152
153    sp<ABuffer> dup = new ABuffer(accessUnit->size() + size);
154    size_t offset = 0;
155    for (size_t i = 0; i < mCSD.size(); ++i) {
156        const sp<ABuffer> &csd = mCSD.itemAt(i);
157
158        memcpy(dup->data() + offset, csd->data(), csd->size());
159        offset += csd->size();
160    }
161
162    memcpy(dup->data() + offset, accessUnit->data(), accessUnit->size());
163
164    return dup;
165}
166
167sp<ABuffer> TSPacketizer::Track::prependADTSHeader(
168        const sp<ABuffer> &accessUnit) const {
169    CHECK_EQ(mCSD.size(), 1u);
170
171    const uint8_t *codec_specific_data = mCSD.itemAt(0)->data();
172
173    const uint32_t aac_frame_length = accessUnit->size() + 7;
174
175    sp<ABuffer> dup = new ABuffer(aac_frame_length);
176
177    unsigned profile = (codec_specific_data[0] >> 3) - 1;
178
179    unsigned sampling_freq_index =
180        ((codec_specific_data[0] & 7) << 1)
181        | (codec_specific_data[1] >> 7);
182
183    unsigned channel_configuration =
184        (codec_specific_data[1] >> 3) & 0x0f;
185
186    uint8_t *ptr = dup->data();
187
188    *ptr++ = 0xff;
189    *ptr++ = 0xf1;  // b11110001, ID=0, layer=0, protection_absent=1
190
191    *ptr++ =
192        profile << 6
193        | sampling_freq_index << 2
194        | ((channel_configuration >> 2) & 1);  // private_bit=0
195
196    // original_copy=0, home=0, copyright_id_bit=0, copyright_id_start=0
197    *ptr++ =
198        (channel_configuration & 3) << 6
199        | aac_frame_length >> 11;
200    *ptr++ = (aac_frame_length >> 3) & 0xff;
201    *ptr++ = (aac_frame_length & 7) << 5;
202
203    // adts_buffer_fullness=0, number_of_raw_data_blocks_in_frame=0
204    *ptr++ = 0;
205
206    memcpy(ptr, accessUnit->data(), accessUnit->size());
207
208    return dup;
209}
210
211////////////////////////////////////////////////////////////////////////////////
212
213TSPacketizer::TSPacketizer()
214    : mPATContinuityCounter(0),
215      mPMTContinuityCounter(0) {
216    initCrcTable();
217}
218
219TSPacketizer::~TSPacketizer() {
220}
221
222ssize_t TSPacketizer::addTrack(const sp<AMessage> &format) {
223    AString mime;
224    CHECK(format->findString("mime", &mime));
225
226    unsigned PIDStart;
227    bool isVideo = !strncasecmp("video/", mime.c_str(), 6);
228    bool isAudio = !strncasecmp("audio/", mime.c_str(), 6);
229
230    if (isVideo) {
231        PIDStart = 0x1011;
232    } else if (isAudio) {
233        PIDStart = 0x1100;
234    } else {
235        return ERROR_UNSUPPORTED;
236    }
237
238    unsigned streamType;
239    unsigned streamIDStart;
240    unsigned streamIDStop;
241
242    if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
243        streamType = 0x1b;
244        streamIDStart = 0xe0;
245        streamIDStop = 0xef;
246    } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_AUDIO_AAC)) {
247        streamType = 0x0f;
248        streamIDStart = 0xc0;
249        streamIDStop = 0xdf;
250    } else {
251        return ERROR_UNSUPPORTED;
252    }
253
254    size_t numTracksOfThisType = 0;
255    unsigned PID = PIDStart;
256
257    for (size_t i = 0; i < mTracks.size(); ++i) {
258        const sp<Track> &track = mTracks.itemAt(i);
259
260        if (track->streamType() == streamType) {
261            ++numTracksOfThisType;
262        }
263
264        if ((isAudio && track->isAudio()) || (isVideo && track->isVideo())) {
265            ++PID;
266        }
267    }
268
269    unsigned streamID = streamIDStart + numTracksOfThisType;
270    if (streamID > streamIDStop) {
271        return -ERANGE;
272    }
273
274    sp<Track> track = new Track(format, PID, streamType, streamID);
275    return mTracks.add(track);
276}
277
278status_t TSPacketizer::packetize(
279        size_t trackIndex,
280        const sp<ABuffer> &_accessUnit,
281        sp<ABuffer> *packets,
282        uint32_t flags,
283        const uint8_t *PES_private_data, size_t PES_private_data_len) {
284    sp<ABuffer> accessUnit = _accessUnit;
285
286    int64_t timeUs;
287    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
288
289    packets->clear();
290
291    if (trackIndex >= mTracks.size()) {
292        return -ERANGE;
293    }
294
295    const sp<Track> &track = mTracks.itemAt(trackIndex);
296
297    if (track->isH264() && (flags & PREPEND_SPS_PPS_TO_IDR_FRAMES)
298            && IsIDR(accessUnit)) {
299        // prepend codec specific data, i.e. SPS and PPS.
300        accessUnit = track->prependCSD(accessUnit);
301    } else if (track->isAudio() && track->lacksADTSHeader()) {
302        CHECK(!(flags & IS_ENCRYPTED));
303        accessUnit = track->prependADTSHeader(accessUnit);
304    }
305
306    // 0x47
307    // transport_error_indicator = b0
308    // payload_unit_start_indicator = b1
309    // transport_priority = b0
310    // PID
311    // transport_scrambling_control = b00
312    // adaptation_field_control = b??
313    // continuity_counter = b????
314    // -- payload follows
315    // packet_startcode_prefix = 0x000001
316    // stream_id
317    // PES_packet_length = 0x????
318    // reserved = b10
319    // PES_scrambling_control = b00
320    // PES_priority = b0
321    // data_alignment_indicator = b1
322    // copyright = b0
323    // original_or_copy = b0
324    // PTS_DTS_flags = b10  (PTS only)
325    // ESCR_flag = b0
326    // ES_rate_flag = b0
327    // DSM_trick_mode_flag = b0
328    // additional_copy_info_flag = b0
329    // PES_CRC_flag = b0
330    // PES_extension_flag = b0
331    // PES_header_data_length = 0x05
332    // reserved = b0010 (PTS)
333    // PTS[32..30] = b???
334    // reserved = b1
335    // PTS[29..15] = b??? ???? ???? ???? (15 bits)
336    // reserved = b1
337    // PTS[14..0] = b??? ???? ???? ???? (15 bits)
338    // reserved = b1
339    // the first fragment of "buffer" follows
340
341    size_t PES_packet_length = accessUnit->size() + 8;
342    if (PES_private_data_len > 0) {
343        PES_packet_length += PES_private_data_len + 1;
344    }
345
346    size_t numTSPackets;
347    if (PES_packet_length <= 178) {
348        numTSPackets = 1;
349    } else {
350        numTSPackets = 1 + ((PES_packet_length - 178) + 183) / 184;
351    }
352
353    if (flags & EMIT_PAT_AND_PMT) {
354        numTSPackets += 2;
355    }
356
357    if (flags & EMIT_PCR) {
358        ++numTSPackets;
359    }
360
361    sp<ABuffer> buffer = new ABuffer(numTSPackets * 188);
362    uint8_t *packetDataStart = buffer->data();
363
364    if (flags & EMIT_PAT_AND_PMT) {
365        // Program Association Table (PAT):
366        // 0x47
367        // transport_error_indicator = b0
368        // payload_unit_start_indicator = b1
369        // transport_priority = b0
370        // PID = b0000000000000 (13 bits)
371        // transport_scrambling_control = b00
372        // adaptation_field_control = b01 (no adaptation field, payload only)
373        // continuity_counter = b????
374        // skip = 0x00
375        // --- payload follows
376        // table_id = 0x00
377        // section_syntax_indicator = b1
378        // must_be_zero = b0
379        // reserved = b11
380        // section_length = 0x00d
381        // transport_stream_id = 0x0000
382        // reserved = b11
383        // version_number = b00001
384        // current_next_indicator = b1
385        // section_number = 0x00
386        // last_section_number = 0x00
387        //   one program follows:
388        //   program_number = 0x0001
389        //   reserved = b111
390        //   program_map_PID = kPID_PMT (13 bits!)
391        // CRC = 0x????????
392
393        if (++mPATContinuityCounter == 16) {
394            mPATContinuityCounter = 0;
395        }
396
397        uint8_t *ptr = packetDataStart;
398        *ptr++ = 0x47;
399        *ptr++ = 0x40;
400        *ptr++ = 0x00;
401        *ptr++ = 0x10 | mPATContinuityCounter;
402        *ptr++ = 0x00;
403
404        const uint8_t *crcDataStart = ptr;
405        *ptr++ = 0x00;
406        *ptr++ = 0xb0;
407        *ptr++ = 0x0d;
408        *ptr++ = 0x00;
409        *ptr++ = 0x00;
410        *ptr++ = 0xc3;
411        *ptr++ = 0x00;
412        *ptr++ = 0x00;
413        *ptr++ = 0x00;
414        *ptr++ = 0x01;
415        *ptr++ = 0xe0 | (kPID_PMT >> 8);
416        *ptr++ = kPID_PMT & 0xff;
417
418        CHECK_EQ(ptr - crcDataStart, 12);
419        uint32_t crc = htonl(crc32(crcDataStart, ptr - crcDataStart));
420        memcpy(ptr, &crc, 4);
421        ptr += 4;
422
423        size_t sizeLeft = packetDataStart + 188 - ptr;
424        memset(ptr, 0xff, sizeLeft);
425
426        packetDataStart += 188;
427
428        // Program Map (PMT):
429        // 0x47
430        // transport_error_indicator = b0
431        // payload_unit_start_indicator = b1
432        // transport_priority = b0
433        // PID = kPID_PMT (13 bits)
434        // transport_scrambling_control = b00
435        // adaptation_field_control = b01 (no adaptation field, payload only)
436        // continuity_counter = b????
437        // skip = 0x00
438        // -- payload follows
439        // table_id = 0x02
440        // section_syntax_indicator = b1
441        // must_be_zero = b0
442        // reserved = b11
443        // section_length = 0x???
444        // program_number = 0x0001
445        // reserved = b11
446        // version_number = b00001
447        // current_next_indicator = b1
448        // section_number = 0x00
449        // last_section_number = 0x00
450        // reserved = b111
451        // PCR_PID = kPCR_PID (13 bits)
452        // reserved = b1111
453        // program_info_length = 0x000
454        //   one or more elementary stream descriptions follow:
455        //   stream_type = 0x??
456        //   reserved = b111
457        //   elementary_PID = b? ???? ???? ???? (13 bits)
458        //   reserved = b1111
459        //   ES_info_length = 0x000
460        // CRC = 0x????????
461
462        if (++mPMTContinuityCounter == 16) {
463            mPMTContinuityCounter = 0;
464        }
465
466        size_t section_length = 5 * mTracks.size() + 4 + 9;
467
468        ptr = packetDataStart;
469        *ptr++ = 0x47;
470        *ptr++ = 0x40 | (kPID_PMT >> 8);
471        *ptr++ = kPID_PMT & 0xff;
472        *ptr++ = 0x10 | mPMTContinuityCounter;
473        *ptr++ = 0x00;
474
475        crcDataStart = ptr;
476        *ptr++ = 0x02;
477        *ptr++ = 0xb0 | (section_length >> 8);
478        *ptr++ = section_length & 0xff;
479        *ptr++ = 0x00;
480        *ptr++ = 0x01;
481        *ptr++ = 0xc3;
482        *ptr++ = 0x00;
483        *ptr++ = 0x00;
484        *ptr++ = 0xe0 | (kPID_PCR >> 8);
485        *ptr++ = kPID_PCR & 0xff;
486        *ptr++ = 0xf0;
487        *ptr++ = 0x00;
488
489        for (size_t i = 0; i < mTracks.size(); ++i) {
490            const sp<Track> &track = mTracks.itemAt(i);
491
492            *ptr++ = track->streamType();
493            *ptr++ = 0xe0 | (track->PID() >> 8);
494            *ptr++ = track->PID() & 0xff;
495            *ptr++ = 0xf0;
496            *ptr++ = 0x00;
497        }
498
499        CHECK_EQ(ptr - crcDataStart, 12 + mTracks.size() * 5);
500        crc = htonl(crc32(crcDataStart, ptr - crcDataStart));
501        memcpy(ptr, &crc, 4);
502        ptr += 4;
503
504        sizeLeft = packetDataStart + 188 - ptr;
505        memset(ptr, 0xff, sizeLeft);
506
507        packetDataStart += 188;
508    }
509
510    if (flags & EMIT_PCR) {
511        // PCR stream
512        // 0x47
513        // transport_error_indicator = b0
514        // payload_unit_start_indicator = b1
515        // transport_priority = b0
516        // PID = kPCR_PID (13 bits)
517        // transport_scrambling_control = b00
518        // adaptation_field_control = b10 (adaptation field only, no payload)
519        // continuity_counter = b0000 (does not increment)
520        // adaptation_field_length = 183
521        // discontinuity_indicator = b0
522        // random_access_indicator = b0
523        // elementary_stream_priority_indicator = b0
524        // PCR_flag = b1
525        // OPCR_flag = b0
526        // splicing_point_flag = b0
527        // transport_private_data_flag = b0
528        // adaptation_field_extension_flag = b0
529        // program_clock_reference_base = b?????????????????????????????????
530        // reserved = b111111
531        // program_clock_reference_extension = b?????????
532
533        int64_t nowUs = ALooper::GetNowUs();
534
535        uint64_t PCR = nowUs * 27;  // PCR based on a 27MHz clock
536        uint64_t PCR_base = PCR / 300;
537        uint32_t PCR_ext = PCR % 300;
538
539        uint8_t *ptr = packetDataStart;
540        *ptr++ = 0x47;
541        *ptr++ = 0x40 | (kPID_PCR >> 8);
542        *ptr++ = kPID_PCR & 0xff;
543        *ptr++ = 0x20;
544        *ptr++ = 0xb7;  // adaptation_field_length
545        *ptr++ = 0x10;
546        *ptr++ = (PCR_base >> 25) & 0xff;
547        *ptr++ = (PCR_base >> 17) & 0xff;
548        *ptr++ = (PCR_base >> 9) & 0xff;
549        *ptr++ = ((PCR_base & 1) << 7) | 0x7e | ((PCR_ext >> 8) & 1);
550        *ptr++ = (PCR_ext & 0xff);
551
552        size_t sizeLeft = packetDataStart + 188 - ptr;
553        memset(ptr, 0xff, sizeLeft);
554
555        packetDataStart += 188;
556    }
557
558    uint64_t PTS = (timeUs * 9ll) / 100ll;
559
560    bool padding = (PES_packet_length < (188 - 10));
561
562    if (PES_packet_length >= 65536) {
563        // This really should only happen for video.
564        CHECK(track->isVideo());
565
566        // It's valid to set this to 0 for video according to the specs.
567        PES_packet_length = 0;
568    }
569
570    uint8_t *ptr = packetDataStart;
571    *ptr++ = 0x47;
572    *ptr++ = 0x40 | (track->PID() >> 8);
573    *ptr++ = track->PID() & 0xff;
574    *ptr++ = (padding ? 0x30 : 0x10) | track->incrementContinuityCounter();
575
576    if (padding) {
577        size_t paddingSize = 188 - 10 - PES_packet_length;
578        *ptr++ = paddingSize - 1;
579        if (paddingSize >= 2) {
580            *ptr++ = 0x00;
581            memset(ptr, 0xff, paddingSize - 2);
582            ptr += paddingSize - 2;
583        }
584    }
585
586    *ptr++ = 0x00;
587    *ptr++ = 0x00;
588    *ptr++ = 0x01;
589    *ptr++ = track->streamID();
590    *ptr++ = PES_packet_length >> 8;
591    *ptr++ = PES_packet_length & 0xff;
592    *ptr++ = 0x84;
593    *ptr++ = (PES_private_data_len > 0) ? 0x81 : 0x80;
594
595    *ptr++ = (PES_private_data_len > 0)
596        ? (1 + PES_private_data_len + 0x05) : 0x05;
597
598    *ptr++ = 0x20 | (((PTS >> 30) & 7) << 1) | 1;
599    *ptr++ = (PTS >> 22) & 0xff;
600    *ptr++ = (((PTS >> 15) & 0x7f) << 1) | 1;
601    *ptr++ = (PTS >> 7) & 0xff;
602    *ptr++ = ((PTS & 0x7f) << 1) | 1;
603
604    if (PES_private_data_len > 0) {
605        *ptr++ = 0x8e;  // PES_private_data_flag, reserved.
606        memcpy(ptr, PES_private_data, PES_private_data_len);
607        ptr += PES_private_data_len;
608    }
609
610    // 18 bytes of TS/PES header leave 188 - 18 = 170 bytes for the payload
611
612    size_t sizeLeft = packetDataStart + 188 - ptr;
613    size_t copy = accessUnit->size();
614    if (copy > sizeLeft) {
615        copy = sizeLeft;
616    }
617
618    memcpy(ptr, accessUnit->data(), copy);
619    ptr += copy;
620    CHECK_EQ(sizeLeft, copy);
621    memset(ptr, 0xff, sizeLeft - copy);
622
623    packetDataStart += 188;
624
625    size_t offset = copy;
626    while (offset < accessUnit->size()) {
627        bool padding = (accessUnit->size() - offset) < (188 - 4);
628
629        // for subsequent fragments of "buffer":
630        // 0x47
631        // transport_error_indicator = b0
632        // payload_unit_start_indicator = b0
633        // transport_priority = b0
634        // PID = b0 0001 1110 ???? (13 bits) [0x1e0 + 1 + sourceIndex]
635        // transport_scrambling_control = b00
636        // adaptation_field_control = b??
637        // continuity_counter = b????
638        // the fragment of "buffer" follows.
639
640        uint8_t *ptr = packetDataStart;
641        *ptr++ = 0x47;
642        *ptr++ = 0x00 | (track->PID() >> 8);
643        *ptr++ = track->PID() & 0xff;
644
645        *ptr++ = (padding ? 0x30 : 0x10) | track->incrementContinuityCounter();
646
647        if (padding) {
648            size_t paddingSize = 188 - 4 - (accessUnit->size() - offset);
649            *ptr++ = paddingSize - 1;
650            if (paddingSize >= 2) {
651                *ptr++ = 0x00;
652                memset(ptr, 0xff, paddingSize - 2);
653                ptr += paddingSize - 2;
654            }
655        }
656
657        // 4 bytes of TS header leave 188 - 4 = 184 bytes for the payload
658
659        size_t sizeLeft = packetDataStart + 188 - ptr;
660        size_t copy = accessUnit->size() - offset;
661        if (copy > sizeLeft) {
662            copy = sizeLeft;
663        }
664
665        memcpy(ptr, accessUnit->data() + offset, copy);
666        ptr += copy;
667        CHECK_EQ(sizeLeft, copy);
668        memset(ptr, 0xff, sizeLeft - copy);
669
670        offset += copy;
671        packetDataStart += 188;
672    }
673
674    CHECK(packetDataStart == buffer->data() + buffer->capacity());
675
676    *packets = buffer;
677
678    return OK;
679}
680
681void TSPacketizer::initCrcTable() {
682    uint32_t poly = 0x04C11DB7;
683
684    for (int i = 0; i < 256; i++) {
685        uint32_t crc = i << 24;
686        for (int j = 0; j < 8; j++) {
687            crc = (crc << 1) ^ ((crc & 0x80000000) ? (poly) : 0);
688        }
689        mCrcTable[i] = crc;
690    }
691}
692
693uint32_t TSPacketizer::crc32(const uint8_t *start, size_t size) const {
694    uint32_t crc = 0xFFFFFFFF;
695    const uint8_t *p;
696
697    for (p = start; p < start + size; ++p) {
698        crc = (crc << 8) ^ mCrcTable[((crc >> 24) ^ *p) & 0xFF];
699    }
700
701    return crc;
702}
703
704sp<ABuffer> TSPacketizer::prependCSD(
705        size_t trackIndex, const sp<ABuffer> &accessUnit) const {
706    CHECK_LT(trackIndex, mTracks.size());
707
708    const sp<Track> &track = mTracks.itemAt(trackIndex);
709    CHECK(track->isH264() && IsIDR(accessUnit));
710
711    int64_t timeUs;
712    CHECK(accessUnit->meta()->findInt64("timeUs", &timeUs));
713
714    sp<ABuffer> accessUnit2 = track->prependCSD(accessUnit);
715
716    accessUnit2->meta()->setInt64("timeUs", timeUs);
717
718    return accessUnit2;
719}
720
721}  // namespace android
722
723