Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 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 | |
| 18 | namespace { |
| 19 | const uint64_t kDebugTrackUid = 0xDEADBEEF; |
| 20 | const int kVideoTrackNumber = 1; |
| 21 | } // namespace |
| 22 | |
| 23 | void write_webm_file_header(struct EbmlGlobal *glob, |
Adrian Grange | cebe6f0 | 2016-03-25 12:11:05 -0700 | [diff] [blame] | 24 | const aom_codec_enc_cfg_t *cfg, |
| 25 | const struct aom_rational *fps, |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 26 | stereo_format_t stereo_fmt, unsigned int fourcc, |
Frank Galligan | 09acd26 | 2015-06-01 10:20:58 -0700 | [diff] [blame] | 27 | const struct VpxRational *par) { |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 28 | mkvmuxer::MkvWriter *const writer = new mkvmuxer::MkvWriter(glob->stream); |
| 29 | mkvmuxer::Segment *const segment = new mkvmuxer::Segment(); |
| 30 | segment->Init(writer); |
| 31 | segment->set_mode(mkvmuxer::Segment::kFile); |
| 32 | segment->OutputCues(true); |
| 33 | |
| 34 | mkvmuxer::SegmentInfo *const info = segment->GetSegmentInfo(); |
| 35 | const uint64_t kTimecodeScale = 1000000; |
| 36 | info->set_timecode_scale(kTimecodeScale); |
Adrian Grange | cebe6f0 | 2016-03-25 12:11:05 -0700 | [diff] [blame] | 37 | std::string version = "aomenc"; |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 38 | if (!glob->debug) { |
Adrian Grange | cebe6f0 | 2016-03-25 12:11:05 -0700 | [diff] [blame] | 39 | version.append(std::string(" ") + aom_codec_version_str()); |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 40 | } |
| 41 | info->set_writing_app(version.c_str()); |
| 42 | |
| 43 | const uint64_t video_track_id = |
| 44 | segment->AddVideoTrack(static_cast<int>(cfg->g_w), |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 45 | static_cast<int>(cfg->g_h), kVideoTrackNumber); |
| 46 | mkvmuxer::VideoTrack *const video_track = static_cast<mkvmuxer::VideoTrack *>( |
| 47 | segment->GetTrackByNumber(video_track_id)); |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 48 | video_track->SetStereoMode(stereo_fmt); |
Yaowu Xu | 3d1bb97 | 2015-08-14 12:30:10 -0700 | [diff] [blame] | 49 | const char *codec_id; |
| 50 | switch (fourcc) { |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 51 | case VP8_FOURCC: codec_id = "V_VP8"; break; |
| 52 | case VP9_FOURCC: codec_id = "V_VP9"; break; |
Yaowu Xu | 01dee0b | 2016-03-25 12:43:01 -0700 | [diff] [blame^] | 53 | case AV1_FOURCC: codec_id = "V_AV1"; break; |
| 54 | default: codec_id = "V_AV1"; break; |
Yaowu Xu | 3d1bb97 | 2015-08-14 12:30:10 -0700 | [diff] [blame] | 55 | } |
| 56 | video_track->set_codec_id(codec_id); |
Frank Galligan | 09acd26 | 2015-06-01 10:20:58 -0700 | [diff] [blame] | 57 | if (par->numerator > 1 || par->denominator > 1) { |
| 58 | // TODO(fgalligan): Add support of DisplayUnit, Display Aspect Ratio type |
| 59 | // to WebM format. |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 60 | const uint64_t display_width = static_cast<uint64_t>( |
| 61 | ((cfg->g_w * par->numerator * 1.0) / par->denominator) + .5); |
Frank Galligan | 09acd26 | 2015-06-01 10:20:58 -0700 | [diff] [blame] | 62 | video_track->set_display_width(display_width); |
| 63 | video_track->set_display_height(cfg->g_h); |
| 64 | } |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 65 | if (glob->debug) { |
| 66 | video_track->set_uid(kDebugTrackUid); |
| 67 | } |
| 68 | glob->writer = writer; |
| 69 | glob->segment = segment; |
| 70 | } |
| 71 | |
Adrian Grange | cebe6f0 | 2016-03-25 12:11:05 -0700 | [diff] [blame] | 72 | void write_webm_block(struct EbmlGlobal *glob, const aom_codec_enc_cfg_t *cfg, |
| 73 | const aom_codec_cx_pkt_t *pkt) { |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 74 | mkvmuxer::Segment *const segment = |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 75 | reinterpret_cast<mkvmuxer::Segment *>(glob->segment); |
| 76 | int64_t pts_ns = pkt->data.frame.pts * 1000000000ll * cfg->g_timebase.num / |
| 77 | cfg->g_timebase.den; |
| 78 | if (pts_ns <= glob->last_pts_ns) pts_ns = glob->last_pts_ns + 1000000; |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 79 | glob->last_pts_ns = pts_ns; |
| 80 | |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 81 | segment->AddFrame(static_cast<uint8_t *>(pkt->data.frame.buf), |
| 82 | pkt->data.frame.sz, kVideoTrackNumber, pts_ns, |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 83 | pkt->data.frame.flags & VPX_FRAME_IS_KEY); |
| 84 | } |
| 85 | |
| 86 | void write_webm_file_footer(struct EbmlGlobal *glob) { |
| 87 | mkvmuxer::MkvWriter *const writer = |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 88 | reinterpret_cast<mkvmuxer::MkvWriter *>(glob->writer); |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 89 | mkvmuxer::Segment *const segment = |
clang-format | 99e28b8 | 2016-01-27 12:42:45 -0800 | [diff] [blame] | 90 | reinterpret_cast<mkvmuxer::Segment *>(glob->segment); |
Vignesh Venkatasubramanian | 2dcbf8c | 2014-03-19 11:56:02 -0700 | [diff] [blame] | 91 | segment->Finalize(); |
| 92 | delete segment; |
| 93 | delete writer; |
| 94 | glob->writer = NULL; |
| 95 | glob->segment = NULL; |
| 96 | } |