bool Header::Write(IOBuffer &buffer) { if (ci < 64) { buffer.ReadFromByte((ht << 6) | ((uint8_t) ci)); } else if (ci < 319) { buffer.ReadFromByte(ht << 6); buffer.ReadFromByte((uint8_t) (ci - 64)); } else if (ci < 65599) { uint16_t temp = EHTONS((uint16_t) (ci - 64)); buffer.ReadFromByte((ht << 6) | 0x01); buffer.ReadFromBuffer((uint8_t *) & temp, 2); } else { FATAL("Invalid channel index"); return false; } switch (ht) { case HT_FULL: { if (hf.s.ts < 0x00ffffff) { hf.s.ts = EHTONL(hf.s.ts); //----MARKED-LONG--- hf.s.ml = EHTONL(hf.s.ml << 8); //----MARKED-LONG--- buffer.ReadFromBuffer(&hf.datac[1], 11); hf.s.ts = ENTOHL(hf.s.ts); //----MARKED-LONG--- hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG--- return true; } else { uint32_t temp = EHTONL(hf.s.ts); //----MARKED-LONG--- hf.s.ts = EHTONL(0x00ffffff); //----MARKED-LONG--- hf.s.ml = EHTONL(hf.s.ml << 8); //----MARKED-LONG--- buffer.ReadFromBuffer(&hf.datac[1], 11); hf.s.ts = ENTOHL(temp); //----MARKED-LONG--- hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG--- buffer.ReadFromBuffer((uint8_t *) & temp, 4); return true; } }
string U32TOS(uint32_t type) { type = ENTOHL(type); return string((char *) & (type), 4); }
void CommonTestsSuite::test_Endianess() { uint16_t ui16 = 0x0102; uint32_t ui32 = 0x01020304; uint64_t ui64 = 0x0102030405060708LL; double d = 123.456; //host to network uint8_t *pBuffer = NULL; ui16 = EHTONS(ui16); pBuffer = (uint8_t *) & ui16; TS_ASSERT(pBuffer[0] == 0x01); TS_ASSERT(pBuffer[1] == 0x02); pBuffer = NULL; ui32 = EHTONL(ui32); pBuffer = (uint8_t *) & ui32; TS_ASSERT(pBuffer[0] == 0x01); TS_ASSERT(pBuffer[1] == 0x02); TS_ASSERT(pBuffer[2] == 0x03); TS_ASSERT(pBuffer[3] == 0x04); pBuffer = NULL; ui32 = 0x01020304; ui32 = EHTONA(ui32); pBuffer = (uint8_t *) & ui32; TS_ASSERT(pBuffer[0] == 0x02); TS_ASSERT(pBuffer[1] == 0x03); TS_ASSERT(pBuffer[2] == 0x04); TS_ASSERT(pBuffer[3] == 0x01); pBuffer = NULL; ui64 = EHTONLL(ui64); pBuffer = (uint8_t *) & ui64; TS_ASSERT(pBuffer[0] == 0x01); TS_ASSERT(pBuffer[1] == 0x02); TS_ASSERT(pBuffer[2] == 0x03); TS_ASSERT(pBuffer[3] == 0x04); TS_ASSERT(pBuffer[4] == 0x05); TS_ASSERT(pBuffer[5] == 0x06); TS_ASSERT(pBuffer[6] == 0x07); TS_ASSERT(pBuffer[7] == 0x08); pBuffer = NULL; EHTOND(d, ui64); pBuffer = (uint8_t *) & ui64; TS_ASSERT(pBuffer[0] == 0x40); TS_ASSERT(pBuffer[1] == 0x5e); TS_ASSERT(pBuffer[2] == 0xdd); TS_ASSERT(pBuffer[3] == 0x2f); TS_ASSERT(pBuffer[4] == 0x1a); TS_ASSERT(pBuffer[5] == 0x9f); TS_ASSERT(pBuffer[6] == 0xbe); TS_ASSERT(pBuffer[7] == 0x77); //network to host pointer char buffer[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; ui16 = ENTOHSP(buffer); TS_ASSERT(ui16 == 0x0001); ui16 = ENTOHSP(buffer + 1); TS_ASSERT(ui16 == 0x0102); ui16 = ENTOHSP(buffer + 2); TS_ASSERT(ui16 == 0x0203); ui16 = ENTOHSP(buffer + 3); TS_ASSERT(ui16 == 0x0304); ui16 = ENTOHSP(buffer + 4); TS_ASSERT(ui16 == 0x0405); ui16 = ENTOHSP(buffer + 5); TS_ASSERT(ui16 == 0x0506); ui16 = ENTOHSP(buffer + 6); TS_ASSERT(ui16 == 0x0607); ui16 = ENTOHSP(buffer + 7); TS_ASSERT(ui16 == 0x0708); ui16 = ENTOHSP(buffer + 8); TS_ASSERT(ui16 == 0x0809); ui16 = ENTOHSP(buffer + 9); TS_ASSERT(ui16 == 0x090a); ui16 = ENTOHSP(buffer + 10); TS_ASSERT(ui16 == 0x0a0b); ui16 = ENTOHSP(buffer + 11); TS_ASSERT(ui16 == 0x0b0c); ui16 = ENTOHSP(buffer + 12); TS_ASSERT(ui16 == 0x0c0d); ui16 = ENTOHSP(buffer + 13); TS_ASSERT(ui16 == 0x0d0e); ui16 = ENTOHSP(buffer + 14); TS_ASSERT(ui16 == 0x0e0f); ui32 = ENTOHLP(buffer); TS_ASSERT(ui32 == 0x00010203); ui32 = ENTOHLP(buffer + 1); TS_ASSERT(ui32 == 0x01020304); ui32 = ENTOHLP(buffer + 2); TS_ASSERT(ui32 == 0x02030405); ui32 = ENTOHLP(buffer + 3); TS_ASSERT(ui32 == 0x03040506); ui32 = ENTOHLP(buffer + 4); TS_ASSERT(ui32 == 0x04050607); ui32 = ENTOHLP(buffer + 5); TS_ASSERT(ui32 == 0x05060708); ui32 = ENTOHLP(buffer + 6); TS_ASSERT(ui32 == 0x06070809); ui32 = ENTOHLP(buffer + 7); TS_ASSERT(ui32 == 0x0708090a); ui32 = ENTOHLP(buffer + 8); TS_ASSERT(ui32 == 0x08090a0b); ui32 = ENTOHLP(buffer + 9); TS_ASSERT(ui32 == 0x090a0b0c); ui32 = ENTOHLP(buffer + 10); TS_ASSERT(ui32 == 0x0a0b0c0d); ui32 = ENTOHLP(buffer + 11); TS_ASSERT(ui32 == 0x0b0c0d0e); ui32 = ENTOHLP(buffer + 12); TS_ASSERT(ui32 == 0x0c0d0e0f); ui32 = ENTOHAP(buffer); TS_ASSERT(ui32 == 0x03000102); ui32 = ENTOHAP(buffer + 1); TS_ASSERT(ui32 == 0x04010203); ui32 = ENTOHAP(buffer + 2); TS_ASSERT(ui32 == 0x05020304); ui32 = ENTOHAP(buffer + 3); TS_ASSERT(ui32 == 0x06030405); ui32 = ENTOHAP(buffer + 4); TS_ASSERT(ui32 == 0x07040506); ui32 = ENTOHAP(buffer + 5); TS_ASSERT(ui32 == 0x08050607); ui32 = ENTOHAP(buffer + 6); TS_ASSERT(ui32 == 0x09060708); ui32 = ENTOHAP(buffer + 7); TS_ASSERT(ui32 == 0x0a070809); ui32 = ENTOHAP(buffer + 8); TS_ASSERT(ui32 == 0x0b08090a); ui32 = ENTOHAP(buffer + 9); TS_ASSERT(ui32 == 0x0c090a0b); ui32 = ENTOHAP(buffer + 10); TS_ASSERT(ui32 == 0x0d0a0b0c); ui32 = ENTOHAP(buffer + 11); TS_ASSERT(ui32 == 0x0e0b0c0d); ui32 = ENTOHAP(buffer + 12); TS_ASSERT(ui32 == 0x0f0c0d0e); ui64 = ENTOHLLP(buffer); TS_ASSERT(ui64 == 0x0001020304050607LL); ui64 = ENTOHLLP(buffer + 1); TS_ASSERT(ui64 == 0x0102030405060708LL); ui64 = ENTOHLLP(buffer + 2); TS_ASSERT(ui64 == 0x0203040506070809LL); ui64 = ENTOHLLP(buffer + 3); TS_ASSERT(ui64 == 0x030405060708090aLL); ui64 = ENTOHLLP(buffer + 4); TS_ASSERT(ui64 == 0x0405060708090a0bLL); ui64 = ENTOHLLP(buffer + 5); TS_ASSERT(ui64 == 0x05060708090a0b0cLL); ui64 = ENTOHLLP(buffer + 6); TS_ASSERT(ui64 == 0x060708090a0b0c0dLL); ui64 = ENTOHLLP(buffer + 7); TS_ASSERT(ui64 == 0x0708090a0b0c0d0eLL); ui64 = ENTOHLLP(buffer + 8); TS_ASSERT(ui64 == 0x08090a0b0c0d0e0fLL); char *pTempBuffer = new char[64 + 8]; unsigned char rawDouble[] = {0x40, 0x5E, 0xDD, 0x2F, 0x1A, 0x9F, 0xBE, 0x77}; double tempDoubleVal = 0; for (int i = 0; i <= 64; i++) { memset(pTempBuffer, 0, i); memcpy(pTempBuffer + i, rawDouble, 8); memset(pTempBuffer + i + 8, 0, 64 + 8 - i - 8); ENTOHDP((pTempBuffer + i), tempDoubleVal); TS_ASSERT(d == tempDoubleVal); } delete[] pTempBuffer; //network to host #ifdef LITTLE_ENDIAN_BYTE_ALIGNED TS_ASSERT(ENTOHA(0x01040302) == 0x01020304); TS_ASSERT(ENTOHLL(0x0807060504030201LL) == 0x0102030405060708LL); ENTOHD(0x77BE9F1A2FDD5E40LL, tempDoubleVal); TS_ASSERT(d == tempDoubleVal); #endif /* LITTLE_ENDIAN_BYTE_ALIGNED */ #ifdef LITTLE_ENDIAN_SHORT_ALIGNED TS_ASSERT(ENTOHA(0x01040302) == 0x01020304); TS_ASSERT(ENTOHLL(0x0807060504030201LL) == 0x0102030405060708LL); ENTOHD(0x77BE9F1A2FDD5E40LL, tempDoubleVal); TS_ASSERT(d == tempDoubleVal); #endif /* LITTLE_ENDIAN_SHORT_ALIGNED */ #ifdef BIG_ENDIAN_BYTE_ALIGNED TS_ASSERT(ENTOHA(0x02030401) == 0x01020304); TS_ASSERT(ENTOHLL(0x0102030405060708LL) == 0x0102030405060708LL); #error ENTOHD not tested #endif /* BIG_ENDIAN_BYTE_ALIGNED */ #ifdef BIG_ENDIAN_SHORT_ALIGNED #error BIG_ENDIAN_SHORT_ALIGNED set of tests not yet implemented!!! Please take care of this first!!! #endif /* BIG_ENDIAN_SHORT_ALIGNED */ //double mirror TS_ASSERT(ENTOHS(EHTONS(0x0102)) == 0x0102); TS_ASSERT(EHTONS(ENTOHS(0x0102)) == 0x0102); TS_ASSERT(ENTOHL(EHTONL(0x01020304)) == 0x01020304); TS_ASSERT(EHTONL(ENTOHL(0x01020304)) == 0x01020304); TS_ASSERT(ENTOHLL(EHTONLL(0x0102030405060708LL)) == 0x0102030405060708LL); TS_ASSERT(EHTONLL(ENTOHLL(0x0102030405060708LL)) == 0x0102030405060708LL); //EHTOND/ENTOHD are different. Requires 2 parameters. So, no double mirror TS_ASSERT(ENTOHA(EHTONA(0x01020304)) == 0x01020304); TS_ASSERT(EHTONA(ENTOHA(0x01020304)) == 0x01020304); // Buffer Put routines for (int i = 0; i < 16; i++) { EHTONSP(buffer + i, 0x0102); TS_ASSERT(ENTOHSP(buffer + i) == 0x0102); EHTONLP(buffer + i, 0x01020304); TS_ASSERT(ENTOHLP(buffer + i) == 0x01020304); EHTONLLP(buffer + i, 0x0102030405060708LL); TS_ASSERT(ENTOHLLP(buffer + i) == 0x0102030405060708LL); EHTONDP(d, (buffer + i)); ENTOHDP(buffer + i, tempDoubleVal); TS_ASSERT(d == tempDoubleVal); } }
bool Header::Read(uint32_t channelId, uint8_t type, IOBuffer &buffer, uint32_t availableBytes) { ht = type; ci = channelId; switch (ht) { case HT_FULL: { isAbsolute = true; if (availableBytes < 11) { readCompleted = false; return true; } memcpy(hf.datac + 1, GETIBPOINTER(buffer), 11); hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG--- hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG--- if (hf.s.ts == 0x00ffffff) { skip4bytes = true; if (availableBytes < 15) { readCompleted = false; return true; } hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 11); readCompleted = true; return buffer.Ignore(15); } else { skip4bytes = false; readCompleted = true; return buffer.Ignore(11); } } case HT_SAME_STREAM: { isAbsolute = false; if (availableBytes < 7) { readCompleted = false; return true; } memcpy(hf.datac + 1, GETIBPOINTER(buffer), 7); hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG--- hf.s.ml = ENTOHL(hf.s.ml) >> 8; //----MARKED-LONG--- if (hf.s.ts == 0x00ffffff) { skip4bytes = true; if (availableBytes < 11) { readCompleted = false; return true; } hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 7); readCompleted = true; return buffer.Ignore(11); } else { skip4bytes = false; readCompleted = true; return buffer.Ignore(7); } } case HT_SAME_LENGTH_AND_STREAM: { isAbsolute = false; if (availableBytes < 3) { readCompleted = false; return true; } memcpy(hf.datac + 1, GETIBPOINTER(buffer), 3); hf.s.ts = ENTOHL(hf.s.ts)&0x00ffffff; //----MARKED-LONG--- if (hf.s.ts == 0x00ffffff) { skip4bytes = true; if (availableBytes < 7) { readCompleted = false; return true; } hf.s.ts = ENTOHLP(GETIBPOINTER(buffer) + 3); readCompleted = true; return buffer.Ignore(7); } else { skip4bytes = false; readCompleted = true; return buffer.Ignore(3); } } case HT_CONTINUATION: { isAbsolute = false; if (skip4bytes) { if (availableBytes < 4) { readCompleted = false; return true; } readCompleted = true; return buffer.Ignore(4); } else { readCompleted = true; return true; } } default: { FATAL("Invalid header type: %hhu", ht); return false; } } }
int MP4Parser::read_frame(File &file, Track *trak, SampleEntry *sentry, Frame *f) { if (!sentry || !f) return -1; int64_t decode_ts = sentry->decode_ts; uint32_t sample_idx = sentry->sample_idx; off_t sample_offset = sentry->sample_offset; uint32_t sample_sz = sentry->sample_sz; // Seek to where it is and read if (!file.seek_to(sample_offset)) { LOGE("Seek to sample_offset(%ld) failed", sample_offset); return -1; } // Read the frame uint8_t *dat = (uint8_t *) malloc(sample_sz+7); // 7 is for adts-header length if (!dat) { LOGE("malloc for sample failed: %s", ERRNOMSG); return -1; } if (!file.read_buffer(trak->video_track ? dat : dat+7, sample_sz)) { LOGE("Read frame failed, sample_offset: %ld, sample_idx: %u, sample_sz: 0x%08x", sample_offset, sample_idx, sample_sz); SAFE_FREE(dat); return -1; } if (trak->video_track) { // Video track bool is_keyframe = false; // Whether this is a keyframe bool got_sps = false; // Keyframe whether has sps & pps // Convert 4bytes nalu-length to 00 00 00 01 uint32_t nalu_offset = 0; while (nalu_offset < sample_sz) { uint32_t nalu_size = ENTOHL(*(uint32_t *)(dat+nalu_offset)); put_be32(dat+nalu_offset, 0x00000001); uint8_t nalu_typ = *(dat+nalu_offset+4)&0x1F; if (nalu_typ == 0x07) { // Keyframe with sps (pps is also followed) got_sps = true; is_keyframe = true; } else if (!got_sps && (nalu_typ == 0x08 || nalu_typ == 0x06 || nalu_typ == 0x05)) { // Keyframe with sps and pps in box "avcC" is_keyframe = true; } // Handle next nalu in this frame nalu_offset += nalu_size + 4; } if (is_keyframe && !got_sps) { // Recover sps&pps from box "avcC" to make it a complete I-Frame AVCDecorderConfigurationRecord &avc_dcr = trak->avcC->avc_dcr; uint8_t *complete_frame = (uint8_t *) malloc ( 4+avc_dcr.sps_length+ 4+avc_dcr.pps_length+ sample_sz); if (!complete_frame) { LOGE("malloc for complete_frame failed: %s", ERRNOMSG); SAFE_FREE(dat); return -1; } // Copy startcode and sps put_be32(complete_frame, 0x00000001); memcpy(complete_frame+4, avc_dcr.sps, avc_dcr.sps_length); // Copy startcode and pps put_be32(complete_frame+4+avc_dcr.sps_length, 0x00000001); memcpy(complete_frame+4+avc_dcr.sps_length+4, avc_dcr.pps, avc_dcr.pps_length); // Copy the rest of video frame memcpy(complete_frame+4+avc_dcr.sps_length+4+avc_dcr.pps_length, dat, sample_sz); SAFE_FREE(dat); // Update the frame statistics sample_sz += 4+avc_dcr.sps_length+4+avc_dcr.pps_length; dat = complete_frame; } } else { // Audio track // Add adts header to the begining of frame generate_adts_header(trak->esds->asc, sample_sz, dat); // Update the frame statistics sample_sz += 7; } return f->make_frame(decode_ts, dat, sample_sz, true, sentry->composition_time); }