void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing, const char *codecId, unsigned int pixelWidth, unsigned int pixelHeight, unsigned int displayWidth, unsigned int displayHeight, double frameRate) { EbmlLoc start; UInt64 trackID; Ebml_StartSubElement(glob, &start, TrackEntry); Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); trackID = generateTrackID(trackNumber); Ebml_SerializeUnsigned(glob, TrackUID, trackID); Ebml_SerializeString(glob, CodecName, "VP8"); // TODO shouldn't be fixed Ebml_SerializeUnsigned(glob, TrackType, 1); // video is always 1 Ebml_SerializeString(glob, CodecID, codecId); { EbmlLoc videoStart; Ebml_StartSubElement(glob, &videoStart, Video); Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth); Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight); if (pixelWidth != displayWidth) { Ebml_SerializeUnsigned(glob, DisplayWidth, displayWidth); } if (pixelHeight != displayHeight) { Ebml_SerializeUnsigned(glob, DisplayHeight, displayHeight); } Ebml_SerializeFloat(glob, FrameRate, frameRate); Ebml_EndSubElement(glob, &videoStart); // Video } Ebml_EndSubElement(glob, &start); // Track Entry }
int Ebml_WriteWebMSeekInfo(EbmlGlobal *ebml) { int rc = VINF_SUCCESS; /* Save the current file pointer */ uint64_t pos = RTFileTell(ebml->file); if (ebml->seek_info_pos) rc = RTFileSeek(ebml->file, ebml->seek_info_pos, RTFILE_SEEK_BEGIN, NULL); else ebml->seek_info_pos = pos; { uint64_t start; if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(ebml, &start, SeekHead); if (RT_SUCCESS(rc)) rc = Ebml_WriteWebMSeekElement(ebml, Tracks, ebml->track_pos); if (RT_SUCCESS(rc)) rc = Ebml_WriteWebMSeekElement(ebml, Cues, ebml->cue_pos); if (RT_SUCCESS(rc)) rc = Ebml_WriteWebMSeekElement(ebml, Info, ebml->segment_info_pos); if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(ebml, start); } { //segment info uint64_t startInfo; uint64_t frame_time; frame_time = (uint64_t)1000 * ebml->framerate.den / ebml->framerate.num; ebml->segment_info_pos = RTFileTell(ebml->file); if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(ebml, &startInfo, Info); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000); if (RT_SUCCESS(rc)) rc = Ebml_SerializeFloat(ebml, Segment_Duration, (double)(ebml->last_pts_ms + frame_time)); char szVersion[64]; RTStrPrintf(szVersion, sizeof(szVersion), "vpxenc%", ebml->debug ? vpx_codec_version_str() : ""); if (RT_SUCCESS(rc)) rc = Ebml_SerializeString(ebml, MuxingApp, szVersion); if (RT_SUCCESS(rc)) rc = Ebml_SerializeString(ebml, WritingApp, szVersion); if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(ebml, startInfo); } return rc; }
void write_webm_seek_info(struct EbmlGlobal *ebml) { off_t pos; EbmlLoc start; EbmlLoc startInfo; uint64_t frame_time; char version_string[64]; /* Save the current stream pointer. */ pos = ftello(ebml->stream); if (ebml->seek_info_pos) fseeko(ebml->stream, ebml->seek_info_pos, SEEK_SET); else ebml->seek_info_pos = pos; Ebml_StartSubElement(ebml, &start, SeekHead); write_webm_seek_element(ebml, Tracks, ebml->track_pos); write_webm_seek_element(ebml, Cues, ebml->cue_pos); write_webm_seek_element(ebml, Info, ebml->segment_info_pos); Ebml_EndSubElement(ebml, &start); /* Create and write the Segment Info. */ if (ebml->debug) { strcpy(version_string, "vpxenc"); } else { strcpy(version_string, "vpxenc "); strncat(version_string, vpx_codec_version_str(), sizeof(version_string) - 1 - strlen(version_string)); } frame_time = (uint64_t)1000 * ebml->framerate.den / ebml->framerate.num; ebml->segment_info_pos = ftello(ebml->stream); Ebml_StartSubElement(ebml, &startInfo, Info); Ebml_SerializeUnsigned(ebml, TimecodeScale, 1000000); Ebml_SerializeFloat(ebml, Segment_Duration, (double)(ebml->last_pts_ms + frame_time)); Ebml_SerializeString(ebml, 0x4D80, version_string); Ebml_SerializeString(ebml, 0x5741, version_string); Ebml_EndSubElement(ebml, &startInfo); }
//------------------------------------------------------------------ void write_webm_seek_info(EbmlGlobal *global) { off_t pos; off_t start; off_t startInfo; uint64_t frame_time; char version_string[64]; /* Save the current stream pointer. */ pos = ftello(global->stream); if (global->seek_info_pos) { fseeko(global->stream, global->seek_info_pos, SEEK_SET); } else { global->seek_info_pos = pos; } Ebml_StartSubElement(global, &start, SeekHead); write_webm_seek_element(global, Tracks, global->track_pos); write_webm_seek_element(global, Cues, global->cue_pos); write_webm_seek_element(global, Info, global->segment_info_pos); Ebml_EndSubElement(global, &start); /* Create and write the Segment Info. */ strcpy(version_string, "DesktopCapture v1.0 - libVPX "); strncat(version_string, vpx_codec_version_str(), sizeof(version_string) - 1 - strlen(version_string)); frame_time = (uint64_t) 1000 * global->framerate.den / global->framerate.num; global->segment_info_pos = ftello(global->stream); Ebml_StartSubElement(global, &startInfo, Info); Ebml_SerializeUnsigned(global, TimecodeScale, 1000000); Ebml_SerializeFloat(global, Segment_Duration, (double) (global->last_pts_ms + frame_time)); Ebml_SerializeString(global, MuxingApp, version_string); Ebml_SerializeString(global, WritingApp, version_string); Ebml_EndSubElement(global, &startInfo); }
void writeVideoTrack(EbmlGlobal *glob, unsigned int trackNumber, int flagLacing, char *codecId, unsigned int pixelWidth, unsigned int pixelHeight, double frameRate) { EbmlLoc start; Ebml_StartSubElement(glob, &start, TrackEntry); Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); UInt64 trackID = generateTrackID(trackNumber); Ebml_SerializeUnsigned(glob, TrackUID, trackID); Ebml_SerializeString(glob, CodecName, "VP8"); Ebml_SerializeUnsigned(glob, TrackType, 1); Ebml_SerializeString(glob, CodecID, codecId); { EbmlLoc videoStart; Ebml_StartSubElement(glob, &videoStart, Video); Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth); Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight); Ebml_SerializeFloat(glob, FrameRate, frameRate); Ebml_EndSubElement(glob, &videoStart); } Ebml_EndSubElement(glob, &start); }
int Ebml_WriteWebMFileHeader(EbmlGlobal *glob, const vpx_codec_enc_cfg_t *cfg, const struct vpx_rational *fps) { int rc = VINF_SUCCESS; { uint64_t start; rc = ebml_StartSubElement(glob, &start, EBML); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, EBMLVersion, 1); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, EBMLReadVersion, 1); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, EBMLMaxIDLength, 4); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, EBMLMaxSizeLength, 8); if (RT_SUCCESS(rc)) rc = Ebml_SerializeString(glob, DocType, "webm"); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, DocTypeVersion, 2); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, DocTypeReadVersion, 2); if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(glob, start); } { if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(glob, &glob->startSegment, Segment); glob->position_reference = RTFileTell(glob->file); glob->framerate = *fps; if (RT_SUCCESS(rc)) rc = Ebml_WriteWebMSeekInfo(glob); { uint64_t trackStart; glob->track_pos = RTFileTell(glob->file); if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(glob, &trackStart, Tracks); { uint32_t trackNumber = 1; uint32_t trackID = 0; uint64_t start; if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(glob, &start, TrackEntry); if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, TrackNumber, trackNumber); glob->track_id_pos = RTFileTell(glob->file); ebml_SerializeUnsigned32(glob, TrackUID, trackID); Ebml_SerializeUnsigned(glob, TrackType, 1); //video is always 1 Ebml_SerializeString(glob, CodecID, "V_VP8"); { uint64_t videoStart; if (RT_SUCCESS(rc)) rc = ebml_StartSubElement(glob, &videoStart, Video); uint32_t pixelWidth = cfg->g_w; if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, PixelWidth, pixelWidth); uint32_t pixelHeight = cfg->g_h; if (RT_SUCCESS(rc)) rc = Ebml_SerializeUnsigned(glob, PixelHeight, pixelHeight); double frameRate = (double)fps->num / (double)fps->den; if (RT_SUCCESS(rc)) rc = Ebml_SerializeFloat(glob, FrameRate, frameRate); if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(glob, videoStart); } if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(glob, start); //Track Entry } if (RT_SUCCESS(rc)) rc = ebml_EndSubElement(glob, trackStart); } // segment element is open } return rc; }