//------------------------------------------------------------------ void Ebml_SerializeUnsigned32(struct EbmlGlobal *global, unsigned int class_id, uint64_t ui) { const unsigned char sizeSerialized = 4 | 0x80; Ebml_WriteID(global, class_id); Ebml_Serialize(global, &sizeSerialized, sizeof(sizeSerialized), 1); Ebml_Serialize(global, &ui, sizeof(ui), 4); }
void Ebml_SerializeFloat(EbmlGlobal *glob, unsigned long class_id, double d) { unsigned char len = 0x88; Ebml_WriteID(glob, class_id); Ebml_Serialize(glob, &len, sizeof(len), 1); Ebml_Serialize(glob, &d, sizeof(d), 8); }
//------------------------------------------------------------------ void Ebml_SerializeUnsigned64(EbmlGlobal *global, unsigned long class_id, uint64_t ui) { unsigned char sizeSerialized = 8 | 0x80; Ebml_WriteID(global, class_id); Ebml_Serialize(global, &sizeSerialized, sizeof(sizeSerialized), 1); Ebml_Serialize(global, &ui, sizeof(ui), 8); }
void writeSimpleBlock(EbmlGlobal *glob, unsigned char trackNumber, short timeCode, int isKeyframe, unsigned char lacingFlag, int discardable, unsigned char *data, unsigned long dataLength) { Ebml_WriteID(glob, SimpleBlock); unsigned long blockLength = 4 + dataLength; blockLength |= 0x10000000; Ebml_Serialize(glob, &blockLength, sizeof(blockLength), 4); trackNumber |= 0x80; Ebml_Write(glob, &trackNumber, 1); Ebml_Serialize(glob, &timeCode, sizeof(timeCode), 2); unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable; Ebml_Write(glob, &flags, 1); Ebml_Write(glob, data, dataLength); }
void writeSimpleBlock(EbmlGlobal *glob, unsigned char trackNumber, short timeCode, int isKeyframe, unsigned char lacingFlag, int discardable, unsigned char *data, unsigned long dataLength) { unsigned long blockLength = 4 + dataLength; unsigned char flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable; Ebml_WriteID(glob, SimpleBlock); blockLength |= 0x10000000; // TODO check length < 0x0FFFFFFFF Ebml_Serialize(glob, &blockLength, sizeof(blockLength), 4); trackNumber |= 0x80; // TODO check track nubmer < 128 Ebml_Write(glob, &trackNumber, 1); // Ebml_WriteSigned16(glob, timeCode,2); //this is 3 bytes Ebml_Serialize(glob, &timeCode, sizeof(timeCode), 2); flags = 0x00 | (isKeyframe ? 0x80 : 0x00) | (lacingFlag << 1) | discardable; Ebml_Write(glob, &flags, 1); Ebml_Write(glob, data, dataLength); }
//------------------------------------------------------------------ void Ebml_StartSubElement(EbmlGlobal *global, off_t *ebmlLoc, unsigned int class_id) { const uint64_t kEbmlUnknownLength = LITERALU64(0x01FFFFFF, 0xFFFFFFFF); Ebml_WriteID(global, class_id); *ebmlLoc = ftello(global->stream); Ebml_Serialize(global, &kEbmlUnknownLength, sizeof(kEbmlUnknownLength), 8); }
//------------------------------------------------------------------ void Ebml_WriteID(EbmlGlobal *global, unsigned long class_id) { int len; if (class_id >= 0x01000000) { len = 4; } else { if (class_id >= 0x00010000) { len = 3; } else { if (class_id >= 0x00000100) { len = 2; } else { len = 1; } } } Ebml_Serialize(global, (void *) &class_id, sizeof(class_id), len); }
void Ebml_StartSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc, unsigned long class_id) { Ebml_WriteID(glob, class_id); assignWide(&ebmlLoc->offset, &glob->offset); //TODO this is always taking 8 bytes, this may need later optimization unsigned long long unknownLen = 0x01FFFFFFFFFFFFFFLLU; Ebml_Serialize(glob, (void *)&unknownLen, 8); //this is a key that says length unknown }
void Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) { unsigned long long size = glob->offset - ebmlLoc->offset - 8; unsigned long long curOffset = glob->offset; glob->offset = ebmlLoc->offset; size |= 0x0100000000000000LLU; Ebml_Serialize(glob, &size, 8); glob->offset = curOffset; }
void Ebml_SerializeUnsigned(EbmlGlobal *glob, unsigned long class_id, unsigned long ui) { unsigned char size = 8; /* size in bytes to output */ unsigned char sizeSerialized = 0; unsigned long minVal; Ebml_WriteID(glob, class_id); minVal = 0x7fLU; /* mask to compare for byte size */ for (size = 1; size < 4; size ++) { if (ui < minVal) { break; } minVal <<= 7; } sizeSerialized = 0x80 | size; Ebml_Serialize(glob, &sizeSerialized, sizeof(sizeSerialized), 1); Ebml_Serialize(glob, &ui, sizeof(ui), size); }
void Ebml_EndSubElement(EbmlGlobal *glob, EbmlLoc *ebmlLoc) { wide currentEndOfFile; assignWide(¤tEndOfFile, &glob->offset); UInt64 sizeOfElement = *(SInt64 *)¤tEndOfFile - *(SInt64 *)&ebmlLoc->offset -8; assignWide(&glob->offset, &ebmlLoc->offset); sizeOfElement |= 0x0100000000000000LLU; Ebml_Serialize(glob, (void *)&sizeOfElement, 8); assignWide(&glob->offset, ¤tEndOfFile); }
void Ebml_WriteID(EbmlGlobal *glob, unsigned long class_id) { int len; if (class_id >= 0x01000000) len = 4; else if (class_id >= 0x00010000) len = 3; else if (class_id >= 0x00000100) len = 2; else len = 1; Ebml_Serialize(glob, (void *)&class_id, sizeof(class_id), len); }
static void Ebml_EndSubElement(struct EbmlGlobal *glob, EbmlLoc *ebmlLoc) { off_t pos; uint64_t size; /* Save the current stream pointer. */ pos = ftello(glob->stream); /* Calculate the size of this element. */ size = pos - *ebmlLoc - 8; size |= LITERALU64(0x01000000, 0x00000000); /* Seek back to the beginning of the element and write the new size. */ fseeko(glob->stream, *ebmlLoc, SEEK_SET); Ebml_Serialize(glob, &size, sizeof(size), 8); /* Reset the stream pointer. */ fseeko(glob->stream, pos, SEEK_SET); }
void Ebml_WriteLen(EbmlGlobal *glob, int64_t val) { /* TODO check and make sure we are not > than 0x0100000000000000LLU */ unsigned char size = 8; /* size in bytes to output */ /* mask to compare for byte size */ int64_t minVal = 0xff; for (size = 1; size < 8; size ++) { if (val < minVal) break; minVal = (minVal << 7); } val |= (((uint64_t)0x80) << ((size - 1) * 7)); Ebml_Serialize(glob, (void *) &val, sizeof(val), size); }
void write_webm_block(struct EbmlGlobal *glob, const vpx_codec_enc_cfg_t *cfg, const vpx_codec_cx_pkt_t *pkt) { unsigned int block_length; unsigned char track_number; uint16_t block_timecode = 0; unsigned char flags; int64_t pts_ms; int start_cluster = 0, is_keyframe; /* Calculate the PTS of this frame in milliseconds. */ pts_ms = pkt->data.frame.pts * 1000 * (uint64_t)cfg->g_timebase.num / (uint64_t)cfg->g_timebase.den; if (pts_ms <= glob->last_pts_ms) pts_ms = glob->last_pts_ms + 1; glob->last_pts_ms = pts_ms; /* Calculate the relative time of this block. */ if (pts_ms - glob->cluster_timecode > SHRT_MAX) start_cluster = 1; else block_timecode = (uint16_t)pts_ms - glob->cluster_timecode; is_keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY); if (start_cluster || is_keyframe) { if (glob->cluster_open) Ebml_EndSubElement(glob, &glob->startCluster); /* Open the new cluster. */ block_timecode = 0; glob->cluster_open = 1; glob->cluster_timecode = (uint32_t)pts_ms; glob->cluster_pos = ftello(glob->stream); Ebml_StartSubElement(glob, &glob->startCluster, Cluster); Ebml_SerializeUnsigned(glob, Timecode, glob->cluster_timecode); /* Save a cue point if this is a keyframe. */ if (is_keyframe) { struct cue_entry *cue, *new_cue_list; new_cue_list = realloc(glob->cue_list, (glob->cues + 1) * sizeof(struct cue_entry)); if (new_cue_list) glob->cue_list = new_cue_list; else fatal("Failed to realloc cue list."); cue = &glob->cue_list[glob->cues]; cue->time = glob->cluster_timecode; cue->loc = glob->cluster_pos; glob->cues++; } } /* Write the Simple Block. */ Ebml_WriteID(glob, SimpleBlock); block_length = (unsigned int)pkt->data.frame.sz + 4; block_length |= 0x10000000; Ebml_Serialize(glob, &block_length, sizeof(block_length), 4); track_number = 1; track_number |= 0x80; Ebml_Write(glob, &track_number, 1); Ebml_Serialize(glob, &block_timecode, sizeof(block_timecode), 2); flags = 0; if (is_keyframe) flags |= 0x80; if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) flags |= 0x08; Ebml_Write(glob, &flags, 1); Ebml_Write(glob, pkt->data.frame.buf, (unsigned int)pkt->data.frame.sz); }
void Ebml_WriteSigned16(EbmlGlobal *glob, short val) { signed long out = ((val & 0x003FFFFF) | 0x00200000) << 8; Ebml_Serialize(glob, &out, sizeof(out), 3); }