Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: media/capture/webm_muxer.cc

Issue 1352243002: Implemented Multiple video track recoding. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/capture/webm_muxer.h ('k') | media/capture/webm_muxer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/capture/webm_muxer.h" 5 #include "media/capture/webm_muxer.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "media/base/limits.h" 8 #include "media/base/limits.h"
9 #include "media/base/video_frame.h" 9 #include "media/base/video_frame.h"
10 #include "ui/gfx/geometry/size.h" 10 #include "ui/gfx/geometry/size.h"
11 11
12 namespace media { 12 namespace media {
13 13
14 static double GetFrameRate(const scoped_refptr<VideoFrame>& video_frame) { 14 static double GetFrameRate(const scoped_refptr<VideoFrame>& video_frame) {
15 const double kZeroFrameRate = 0.0; 15 const double kZeroFrameRate = 0.0;
16 const double kDefaultFrameRate = 30.0; 16 const double kDefaultFrameRate = 30.0;
17 17
18 double frame_rate = kDefaultFrameRate; 18 double frame_rate = kDefaultFrameRate;
19 if (!video_frame->metadata()->GetDouble( 19 if (!video_frame->metadata()->GetDouble(
20 VideoFrameMetadata::FRAME_RATE, &frame_rate) || 20 VideoFrameMetadata::FRAME_RATE, &frame_rate) ||
21 frame_rate <= kZeroFrameRate || 21 frame_rate <= kZeroFrameRate ||
22 frame_rate > media::limits::kMaxFramesPerSecond) { 22 frame_rate > media::limits::kMaxFramesPerSecond) {
23 frame_rate = kDefaultFrameRate; 23 frame_rate = kDefaultFrameRate;
24 } 24 }
25 return frame_rate; 25 return frame_rate;
26 } 26 }
27 27
28 WebmMuxer::WebmMuxer(const WriteDataCB& write_data_callback) 28 WebmMuxer::WebmMuxer(const WriteDataCB& write_data_callback)
29 : track_index_(0), 29 : write_data_callback_(write_data_callback), position_(0) {
30 write_data_callback_(write_data_callback),
31 position_(0) {
32 DCHECK(!write_data_callback_.is_null()); 30 DCHECK(!write_data_callback_.is_null());
31
32 segment_.Init(this);
33 segment_.set_mode(mkvmuxer::Segment::kLive);
34 segment_.OutputCues(false);
35
36 mkvmuxer::SegmentInfo* const info = segment_.GetSegmentInfo();
37 info->set_writing_app("Chrome");
38 info->set_muxing_app("Chrome");
39
33 // Creation is done on a different thread than main activities. 40 // Creation is done on a different thread than main activities.
34 thread_checker_.DetachFromThread(); 41 thread_checker_.DetachFromThread();
35 } 42 }
36 43
37 WebmMuxer::~WebmMuxer() { 44 WebmMuxer::~WebmMuxer() {
38 // No need to segment_.Finalize() since is not Seekable(), i.e. a live 45 // No need to segment_.Finalize() since is not Seekable(), i.e. a live
39 // stream, but is a good practice. 46 // stream, but is a good practice.
40 DCHECK(thread_checker_.CalledOnValidThread()); 47 DCHECK(thread_checker_.CalledOnValidThread());
41 segment_.Finalize(); 48 segment_.Finalize();
42 } 49 }
43 50
44 void WebmMuxer::OnEncodedVideo(const scoped_refptr<VideoFrame>& video_frame, 51 WebmMuxer::EncodedVideoCB WebmMuxer::GenerateOnEncodedVideoCallback() {
52 return base::Bind(&WebmMuxer::OnEncodedVideo, base::Unretained(this),
53 GetNextVideoTrackIndex());
54 }
55
56 void WebmMuxer::OnEncodedVideo(int track_index,
57 const scoped_refptr<VideoFrame>& video_frame,
45 scoped_ptr<std::string> encoded_data, 58 scoped_ptr<std::string> encoded_data,
46 base::TimeTicks timestamp, 59 base::TimeTicks timestamp,
47 bool is_key_frame) { 60 bool is_key_frame) {
48 DVLOG(1) << __FUNCTION__ << " - " << encoded_data->size() << "B"; 61 DVLOG(1) << __FUNCTION__ << " - " << encoded_data->size() << "B";
49 DCHECK(thread_checker_.CalledOnValidThread()); 62 DCHECK(thread_checker_.CalledOnValidThread());
50 if (!track_index_) { 63 int args_size = video_muxer_args_.size();
51 // |track_index_|, cannot be zero (!), initialize WebmMuxer in that case. 64 DCHECK(track_index <= args_size);
65
66 if (args_size == 0 || args_size == track_index) {
67 // If the track is not added muxer, add it in here.
52 // http://www.matroska.org/technical/specs/index.html#Tracks 68 // http://www.matroska.org/technical/specs/index.html#Tracks
53 AddVideoTrack(video_frame->visible_rect().size(), 69 uint64 track_num = AddVideoTrack(video_frame->visible_rect().size(),
54 GetFrameRate(video_frame)); 70 GetFrameRate(video_frame));
55 first_frame_timestamp_ = timestamp; 71 video_muxer_args_.emplace_back(VideoMuxerArg(timestamp, track_num));
56 } 72 }
57 segment_.AddFrame(reinterpret_cast<const uint8_t*>(encoded_data->data()), 73
58 encoded_data->size(), 74 base::TimeDelta timestamp_delta =
59 track_index_, 75 timestamp - video_muxer_args_[track_index].first_frame_timestamp;
60 (timestamp - first_frame_timestamp_).InMicroseconds() * 76 segment_.AddFrame(
61 base::Time::kNanosecondsPerMicrosecond, 77 reinterpret_cast<const uint8_t*>(encoded_data->data()),
62 is_key_frame); 78 encoded_data->size(),
79 video_muxer_args_[track_index].track_number,
80 timestamp_delta.InMicroseconds() * base::Time::kNanosecondsPerMicrosecond,
81 is_key_frame);
63 } 82 }
64 83
65 void WebmMuxer::AddVideoTrack(const gfx::Size& frame_size, double frame_rate) { 84 int WebmMuxer::GetNextVideoTrackIndex() const {
85 return video_muxer_args_.size();
86 }
87
88 uint64 WebmMuxer::AddVideoTrack(
89 const gfx::Size& frame_size, double frame_rate) {
66 DCHECK(thread_checker_.CalledOnValidThread()); 90 DCHECK(thread_checker_.CalledOnValidThread());
67 DCHECK_EQ(track_index_, 0u) << "WebmMuxer can only be initialised once.";
68 91
69 segment_.Init(this); 92 uint64 track_num =
70 segment_.set_mode(mkvmuxer::Segment::kLive);
71 segment_.OutputCues(false);
72
73 mkvmuxer::SegmentInfo* const info = segment_.GetSegmentInfo();
74 info->set_writing_app("Chrome");
75 info->set_muxing_app("Chrome");
76
77 track_index_ =
78 segment_.AddVideoTrack(frame_size.width(), frame_size.height(), 0); 93 segment_.AddVideoTrack(frame_size.width(), frame_size.height(), 0);
79 DCHECK_GT(track_index_, 0u); 94 DCHECK_GT(track_num, 0u);
80 95
81 mkvmuxer::VideoTrack* const video_track = 96 mkvmuxer::VideoTrack* const video_track =
82 reinterpret_cast<mkvmuxer::VideoTrack*>( 97 reinterpret_cast<mkvmuxer::VideoTrack*>(
83 segment_.GetTrackByNumber(track_index_)); 98 segment_.GetTrackByNumber(track_num));
84 DCHECK(video_track); 99 DCHECK(video_track);
85 video_track->set_codec_id(mkvmuxer::Tracks::kVp8CodecId); 100 video_track->set_codec_id(mkvmuxer::Tracks::kVp8CodecId);
86 DCHECK_EQ(video_track->crop_right(), 0ull); 101 DCHECK_EQ(video_track->crop_right(), 0ull);
87 DCHECK_EQ(video_track->crop_left(), 0ull); 102 DCHECK_EQ(video_track->crop_left(), 0ull);
88 DCHECK_EQ(video_track->crop_top(), 0ull); 103 DCHECK_EQ(video_track->crop_top(), 0ull);
89 DCHECK_EQ(video_track->crop_bottom(), 0ull); 104 DCHECK_EQ(video_track->crop_bottom(), 0ull);
90 105
91 video_track->set_frame_rate(frame_rate); 106 video_track->set_frame_rate(frame_rate);
92 video_track->set_default_duration(base::Time::kNanosecondsPerSecond / 107 video_track->set_default_duration(base::Time::kNanosecondsPerSecond /
93 frame_rate); 108 frame_rate);
94 // Segment's timestamps should be in milliseconds, DCHECK it. See 109 // Segment's timestamps should be in milliseconds, DCHECK it. See
95 // http://www.webmproject.org/docs/container/#muxer-guidelines 110 // http://www.webmproject.org/docs/container/#muxer-guidelines
96 DCHECK_EQ(segment_.GetSegmentInfo()->timecode_scale(), 1000000ull); 111 DCHECK_EQ(segment_.GetSegmentInfo()->timecode_scale(), 1000000ull);
112
113 return track_num;
97 } 114 }
98 115
99 mkvmuxer::int32 WebmMuxer::Write(const void* buf, mkvmuxer::uint32 len) { 116 mkvmuxer::int32 WebmMuxer::Write(const void* buf, mkvmuxer::uint32 len) {
100 DCHECK(thread_checker_.CalledOnValidThread()); 117 DCHECK(thread_checker_.CalledOnValidThread());
101 DCHECK(buf); 118 DCHECK(buf);
102 write_data_callback_.Run(base::StringPiece(reinterpret_cast<const char*>(buf), 119 write_data_callback_.Run(base::StringPiece(reinterpret_cast<const char*>(buf),
103 len)); 120 len));
104 position_ += len; 121 position_ += len;
105 return 0; 122 return 0;
106 } 123 }
(...skipping 12 matching lines...) Expand all
119 } 136 }
120 137
121 void WebmMuxer::ElementStartNotify(mkvmuxer::uint64 element_id, 138 void WebmMuxer::ElementStartNotify(mkvmuxer::uint64 element_id,
122 mkvmuxer::int64 position) { 139 mkvmuxer::int64 position) {
123 // This method gets pinged before items are sent to |write_data_callback_|. 140 // This method gets pinged before items are sent to |write_data_callback_|.
124 DCHECK_GE(position, position_.ValueOrDefault(0)) 141 DCHECK_GE(position, position_.ValueOrDefault(0))
125 << "Can't go back in a live WebM stream."; 142 << "Can't go back in a live WebM stream.";
126 } 143 }
127 144
128 } // namespace media 145 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/webm_muxer.h ('k') | media/capture/webm_muxer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698