sp<MetaData> MakeAVCCodecSpecificData(const sp<ABuffer> &accessUnit) { const uint8_t *data = accessUnit->data(); size_t size = accessUnit->size(); sp<ABuffer> seqParamSet = FindNAL(data, size, 7, NULL); if (seqParamSet == NULL) { return NULL; } int32_t width, height; FindAVCDimensions(seqParamSet, &width, &height); size_t stopOffset; sp<ABuffer> picParamSet = FindNAL(data, size, 8, &stopOffset); CHECK(picParamSet != NULL); size_t csdSize = 1 + 3 + 1 + 1 + 2 * 1 + seqParamSet->size() + 1 + 2 * 1 + picParamSet->size(); sp<ABuffer> csd = new ABuffer(csdSize); uint8_t *out = csd->data(); *out++ = 0x01; // configurationVersion memcpy(out, seqParamSet->data() + 1, 3); // profile/level... uint8_t profile = out[0]; uint8_t level = out[2]; out += 3; *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes *out++ = 0xe0 | 1; *out++ = seqParamSet->size() >> 8; *out++ = seqParamSet->size() & 0xff; memcpy(out, seqParamSet->data(), seqParamSet->size()); out += seqParamSet->size(); *out++ = 1; *out++ = picParamSet->size() >> 8; *out++ = picParamSet->size() & 0xff; memcpy(out, picParamSet->data(), picParamSet->size()); #if 0 LOGI("AVC seq param set"); hexdump(seqParamSet->data(), seqParamSet->size()); #endif sp<MetaData> meta = new MetaData; meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); meta->setData(kKeyAVCC, kTypeAVCC, csd->data(), csd->size()); meta->setInt32(kKeyWidth, width); meta->setInt32(kKeyHeight, height); LOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)", width, height, AVCProfileToString(profile), level / 10, level % 10); return meta; }
sp<ABuffer> MakeAVCCodecSpecificData( const sp<ABuffer> &accessUnit, int32_t *width, int32_t *height, int32_t *sarWidth, int32_t *sarHeight) { const uint8_t *data = accessUnit->data(); size_t size = accessUnit->size(); sp<ABuffer> seqParamSet = FindNAL(data, size, 7); if (seqParamSet == NULL) { return NULL; } FindAVCDimensions( seqParamSet, width, height, sarWidth, sarHeight); sp<ABuffer> picParamSet = FindNAL(data, size, 8); CHECK(picParamSet != NULL); size_t csdSize = 1 + 3 + 1 + 1 + 2 * 1 + seqParamSet->size() + 1 + 2 * 1 + picParamSet->size(); sp<ABuffer> csd = new ABuffer(csdSize); uint8_t *out = csd->data(); *out++ = 0x01; // configurationVersion memcpy(out, seqParamSet->data() + 1, 3); // profile/level... uint8_t profile = out[0]; uint8_t level = out[2]; out += 3; *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes *out++ = 0xe0 | 1; *out++ = seqParamSet->size() >> 8; *out++ = seqParamSet->size() & 0xff; memcpy(out, seqParamSet->data(), seqParamSet->size()); out += seqParamSet->size(); *out++ = 1; *out++ = picParamSet->size() >> 8; *out++ = picParamSet->size() & 0xff; memcpy(out, picParamSet->data(), picParamSet->size()); #if 0 ALOGI("AVC seq param set"); hexdump(seqParamSet->data(), seqParamSet->size()); #endif if (sarWidth != nullptr && sarHeight != nullptr) { if ((*sarWidth > 0 && *sarHeight > 0) && (*sarWidth != 1 || *sarHeight != 1)) { ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d) " "SAR %d : %d", *width, *height, AVCProfileToString(profile), level / 10, level % 10, *sarWidth, *sarHeight); } else { // We treat *:0 and 0:* (unspecified) as 1:1. *sarWidth = 0; *sarHeight = 0; ALOGI("found AVC codec config (%d x %d, %s-profile level %d.%d)", *width, *height, AVCProfileToString(profile), level / 10, level % 10); } } return csd; }