1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/capture/webm_muxer.h"
10 #include "media/base/video_frame.h"
14 static double GetFrameRate(const scoped_refptr
<VideoFrame
>& video_frame
) {
15 double frame_rate
= 0.0f
;
16 base::IgnoreResult(video_frame
->metadata()->GetDouble(
17 VideoFrameMetadata::FRAME_RATE
, &frame_rate
));
21 WebmMuxer::WebmMuxer(const WriteDataCB
& write_data_callback
)
23 write_data_callback_(write_data_callback
),
25 DCHECK(thread_checker_
.CalledOnValidThread());
26 DCHECK(!write_data_callback_
.is_null());
28 segment_
.set_mode(mkvmuxer::Segment::kLive
);
29 segment_
.OutputCues(false);
31 mkvmuxer::SegmentInfo
* const info
= segment_
.GetSegmentInfo();
32 info
->set_writing_app("Chrome");
33 info
->set_muxing_app("Chrome");
36 WebmMuxer::~WebmMuxer() {
37 DCHECK(thread_checker_
.CalledOnValidThread());
41 void WebmMuxer::OnEncodedVideo(const scoped_refptr
<VideoFrame
>& video_frame
,
42 const base::StringPiece
& encoded_data
,
43 base::TimeTicks timestamp
,
45 DCHECK(thread_checker_
.CalledOnValidThread());
47 // |track_index_|, cannot be zero (!), initialize WebmMuxer in that case.
48 // http://www.matroska.org/technical/specs/index.html#Tracks
49 AddVideoTrack(video_frame
->visible_rect().size(),
50 GetFrameRate(video_frame
));
51 first_frame_timestamp_
= timestamp
;
53 segment_
.AddFrame(reinterpret_cast<const uint8_t*>(encoded_data
.data()),
56 (timestamp
- first_frame_timestamp_
).InMilliseconds(),
60 void WebmMuxer::AddVideoTrack(const gfx::Size
& frame_size
, double frame_rate
) {
61 DCHECK(thread_checker_
.CalledOnValidThread());
62 DCHECK_EQ(track_index_
, 0u);
64 segment_
.AddVideoTrack(frame_size
.width(), frame_size
.height(), 0);
65 DCHECK_GT(track_index_
, 0u);
67 mkvmuxer::VideoTrack
* const video_track
=
68 reinterpret_cast<mkvmuxer::VideoTrack
*>(
69 segment_
.GetTrackByNumber(track_index_
));
71 video_track
->set_codec_id(mkvmuxer::Tracks::kVp8CodecId
);
72 DCHECK_EQ(video_track
->crop_right(), 0ull);
73 DCHECK_EQ(video_track
->crop_left(), 0ull);
74 DCHECK_EQ(video_track
->crop_top(), 0ull);
75 DCHECK_EQ(video_track
->crop_bottom(), 0ull);
77 video_track
->set_frame_rate(frame_rate
);
78 video_track
->set_default_duration(base::Time::kMicrosecondsPerSecond
/
80 // Segment's timestamps should be in milliseconds, DCHECK it. See
81 // http://www.webmproject.org/docs/container/#muxer-guidelines
82 DCHECK_EQ(segment_
.GetSegmentInfo()->timecode_scale(), 1000000ull);
85 mkvmuxer::int32
WebmMuxer::Write(const void* buf
, mkvmuxer::uint32 len
) {
86 DCHECK(thread_checker_
.CalledOnValidThread());
88 write_data_callback_
.Run(base::StringPiece(reinterpret_cast<const char*>(buf
),
94 mkvmuxer::int64
WebmMuxer::Position() const {
95 return position_
.ValueOrDie();
98 mkvmuxer::int32
WebmMuxer::Position(mkvmuxer::int64 position
) {
99 // The stream is not Seekable() so indicate we cannot set the position.
103 bool WebmMuxer::Seekable() const {
107 void WebmMuxer::ElementStartNotify(mkvmuxer::uint64 element_id
,
108 mkvmuxer::int64 position
) {
109 // This method gets pinged before items are sent to |write_data_callback_|.
110 DCHECK_GE(position
, position_
.ValueOrDefault(0))
111 << "Can't go back in a live WebM stream.";