void write_webm_file_header(struct EbmlGlobal *glob, const vpx_codec_enc_cfg_t *cfg, const struct vpx_rational *fps, stereo_format_t stereo_fmt, unsigned int fourcc) { EbmlLoc start; EbmlLoc trackStart; EbmlLoc videoStart; unsigned int trackNumber = 1; uint64_t trackID = 0; unsigned int pixelWidth = cfg->g_w; unsigned int pixelHeight = cfg->g_h; /* Write the EBML header. */ Ebml_StartSubElement(glob, &start, EBML); Ebml_SerializeUnsigned(glob, EBMLVersion, 1); Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); Ebml_SerializeString(glob, DocType, "webm"); Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); Ebml_EndSubElement(glob, &start); /* Open and begin writing the segment element. */ Ebml_StartSubElement(glob, &glob->startSegment, Segment); glob->position_reference = ftello(glob->stream); glob->framerate = *fps; write_webm_seek_info(glob); /* Open and write the Tracks element. */ glob->track_pos = ftello(glob->stream); Ebml_StartSubElement(glob, &trackStart, Tracks); /* Open and write the Track entry. */ Ebml_StartSubElement(glob, &start, TrackEntry); Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); glob->track_id_pos = ftello(glob->stream); Ebml_SerializeUnsigned32(glob, TrackUID, trackID); Ebml_SerializeUnsigned(glob, TrackType, 1); Ebml_SerializeString(glob, CodecID, fourcc == VP8_FOURCC ? "V_VP8" : "V_VP9"); Ebml_StartSubElement(glob, &videoStart, Video); Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth); Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight); Ebml_SerializeUnsigned(glob, StereoMode, stereo_fmt); Ebml_EndSubElement(glob, &videoStart); /* Close Track entry. */ Ebml_EndSubElement(glob, &start); /* Close Tracks element. */ Ebml_EndSubElement(glob, &trackStart); /* Segment element remains open. */ }
//------------------------------------------------------------------ void write_webm_file_header(EbmlGlobal *global, const vpx_codec_enc_cfg_t *cfg, const struct vpx_rational *fps) { off_t start; off_t trackStart; off_t videoStart; unsigned int trackNumber = 1; uint64_t trackID = 0; unsigned int pixelWidth = cfg->g_w; unsigned int pixelHeight = cfg->g_h; /* Write the EBML header. */ Ebml_StartSubElement(global, &start, EBML); Ebml_SerializeUnsigned(global, EBMLVersion, 1); Ebml_SerializeUnsigned(global, EBMLReadVersion, 1); Ebml_SerializeUnsigned(global, EBMLMaxIDLength, 4); Ebml_SerializeUnsigned(global, EBMLMaxSizeLength, 8); Ebml_SerializeString(global, DocType, "webm"); Ebml_SerializeUnsigned(global, DocTypeVersion, 2); Ebml_SerializeUnsigned(global, DocTypeReadVersion, 2); Ebml_EndSubElement(global, &start); /* Open and begin writing the segment element. */ Ebml_StartSubElement(global, &global->startSegment, Segment); global->position_reference = ftello(global->stream); global->framerate = *fps; write_webm_seek_info(global); /* Open and write the Tracks element. */ global->track_pos = ftello(global->stream); Ebml_StartSubElement(global, &trackStart, Tracks); /* Open and write the Track entry. */ Ebml_StartSubElement(global, &start, TrackEntry); Ebml_SerializeUnsigned(global, TrackNumber, trackNumber); global->track_id_pos = ftello(global->stream); Ebml_SerializeUnsigned32(global, TrackUID, trackID); Ebml_SerializeUnsigned(global, TrackType, 1); Ebml_SerializeString(global, CodecID, "V_VP8"); Ebml_StartSubElement(global, &videoStart, Video); Ebml_SerializeUnsigned(global, PixelWidth, pixelWidth); Ebml_SerializeUnsigned(global, PixelHeight, pixelHeight); Ebml_SerializeUnsigned(global, StereoMode, STEREO_FORMAT_MONO); Ebml_EndSubElement(global, &videoStart); /* Close Track entry. */ Ebml_EndSubElement(global, &start); /* Close Tracks element. */ Ebml_EndSubElement(global, &trackStart); /* Segment element remains open. */ }
//------------------------------------------------------------------ void write_webm_file_footer(EbmlGlobal *global, int hash) { off_t start_cues; off_t start_cue_point; off_t start_cue_tracks; unsigned int i; if (global->cluster_open) { Ebml_EndSubElement(global, &global->startCluster); } global->cue_pos = ftello(global->stream); Ebml_StartSubElement(global, &start_cues, Cues); for (i = 0; i < global->cues; i++) { struct cue_entry *cue = &global->cue_list[i]; Ebml_StartSubElement(global, &start_cue_point, CuePoint); Ebml_SerializeUnsigned(global, CueTime, cue->time); Ebml_StartSubElement(global, &start_cue_tracks, CueTrackPositions); Ebml_SerializeUnsigned(global, CueTrack, 1); Ebml_SerializeUnsigned64(global, CueClusterPosition, cue->loc - global->position_reference); Ebml_EndSubElement(global, &start_cue_tracks); Ebml_EndSubElement(global, &start_cue_point); } Ebml_EndSubElement(global, &start_cues); /* Close the Segment. */ Ebml_EndSubElement(global, &global->startSegment); /* Patch up the seek info block. */ write_webm_seek_info(global); /* Patch up the track id. */ fseeko(global->stream, global->track_id_pos, SEEK_SET); Ebml_SerializeUnsigned32(global, TrackUID, hash); fseeko(global->stream, 0, SEEK_END); }