1/* 2 * Copyright (c) 2014 The WebM project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10#include "./webmenc.h" 11 12#include <string> 13 14#include "third_party/libwebm/mkvmuxer.hpp" 15#include "third_party/libwebm/mkvmuxerutil.hpp" 16#include "third_party/libwebm/mkvwriter.hpp" 17 18namespace { 19const uint64_t kDebugTrackUid = 0xDEADBEEF; 20const int kVideoTrackNumber = 1; 21} // namespace 22 23void write_webm_file_header(struct EbmlGlobal *glob, 24 const vpx_codec_enc_cfg_t *cfg, 25 const struct vpx_rational *fps, 26 stereo_format_t stereo_fmt, 27 unsigned int fourcc, 28 const struct VpxRational *par) { 29 mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(glob->stream); 30 mkvmuxer::Segment *const segment = new mkvmuxer::Segment(); 31 segment->Init(writer); 32 segment->set_mode(mkvmuxer::Segment::kFile); 33 segment->OutputCues(true); 34 35 mkvmuxer::SegmentInfo *const info = segment->GetSegmentInfo(); 36 const uint64_t kTimecodeScale = 1000000; 37 info->set_timecode_scale(kTimecodeScale); 38 std::string version = "vpxenc"; 39 if (!glob->debug) { 40 version.append(std::string(" ") + vpx_codec_version_str()); 41 } 42 info->set_writing_app(version.c_str()); 43 44 const uint64_t video_track_id = 45 segment->AddVideoTrack(static_cast<int>(cfg->g_w), 46 static_cast<int>(cfg->g_h), 47 kVideoTrackNumber); 48 mkvmuxer::VideoTrack* const video_track = 49 static_cast<mkvmuxer::VideoTrack*>( 50 segment->GetTrackByNumber(video_track_id)); 51 video_track->SetStereoMode(stereo_fmt); 52 const char *codec_id; 53 switch (fourcc) { 54 case VP8_FOURCC: 55 codec_id = "V_VP8"; 56 break; 57 case VP9_FOURCC: 58 codec_id = "V_VP9"; 59 break; 60 case VP10_FOURCC: 61 codec_id = "V_VP10"; 62 break; 63 default: 64 codec_id = "V_VP10"; 65 break; 66 } 67 video_track->set_codec_id(codec_id); 68 if (par->numerator > 1 || par->denominator > 1) { 69 // TODO(fgalligan): Add support of DisplayUnit, Display Aspect Ratio type 70 // to WebM format. 71 const uint64_t display_width = 72 static_cast<uint64_t>(((cfg->g_w * par->numerator * 1.0) / 73 par->denominator) + .5); 74 video_track->set_display_width(display_width); 75 video_track->set_display_height(cfg->g_h); 76 } 77 if (glob->debug) { 78 video_track->set_uid(kDebugTrackUid); 79 } 80 glob->writer = writer; 81 glob->segment = segment; 82} 83 84void write_webm_block(struct EbmlGlobal *glob, 85 const vpx_codec_enc_cfg_t *cfg, 86 const vpx_codec_cx_pkt_t *pkt) { 87 mkvmuxer::Segment *const segment = 88 reinterpret_cast<mkvmuxer::Segment*>(glob->segment); 89 int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * 90 cfg->g_timebase.num / cfg->g_timebase.den; 91 if (pts_ns <= glob->last_pts_ns) 92 pts_ns = glob->last_pts_ns + 1000000; 93 glob->last_pts_ns = pts_ns; 94 95 segment->AddFrame(static_cast<uint8_t*>(pkt->data.frame.buf), 96 pkt->data.frame.sz, 97 kVideoTrackNumber, 98 pts_ns, 99 pkt->data.frame.flags & VPX_FRAME_IS_KEY); 100} 101 102void write_webm_file_footer(struct EbmlGlobal *glob) { 103 mkvmuxer::MkvWriter *const writer = 104 reinterpret_cast<mkvmuxer::MkvWriter*>(glob->writer); 105 mkvmuxer::Segment *const segment = 106 reinterpret_cast<mkvmuxer::Segment*>(glob->segment); 107 segment->Finalize(); 108 delete segment; 109 delete writer; 110 glob->writer = NULL; 111 glob->segment = NULL; 112} 113