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

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
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 void WebmMuxer::OnEncodedVideo(int track_index,
52 const scoped_refptr<VideoFrame>& video_frame,
45 scoped_ptr<std::string> encoded_data, 53 scoped_ptr<std::string> encoded_data,
46 base::TimeTicks timestamp, 54 base::TimeTicks timestamp,
47 bool is_key_frame) { 55 bool is_key_frame) {
48 DVLOG(1) << __FUNCTION__ << " - " << encoded_data->size() << "B"; 56 DVLOG(1) << __FUNCTION__ << " - " << encoded_data->size() << "B";
49 DCHECK(thread_checker_.CalledOnValidThread()); 57 DCHECK(thread_checker_.CalledOnValidThread());
50 if (!track_index_) { 58 int args_size = video_muxer_args_.size();
51 // |track_index_|, cannot be zero (!), initialize WebmMuxer in that case. 59 DCHECK(track_index <= args_size);
60
61 if (args_size == 0 || args_size == track_index) {
62 // If the track is not added muxer, add it in here.
52 // http://www.matroska.org/technical/specs/index.html#Tracks 63 // http://www.matroska.org/technical/specs/index.html#Tracks
53 AddVideoTrack(video_frame->visible_rect().size(), 64 uint64 track_num = AddVideoTrack(video_frame->visible_rect().size(),
54 GetFrameRate(video_frame)); 65 GetFrameRate(video_frame));
55 first_frame_timestamp_ = timestamp; 66 video_muxer_args_.emplace_back(VideoMuxerArg(timestamp, track_num));
56 } 67 }
57 segment_.AddFrame(reinterpret_cast<const uint8_t*>(encoded_data->data()), 68
58 encoded_data->size(), 69 base::TimeDelta timestamp_delta =
59 track_index_, 70 timestamp - video_muxer_args_[track_index].first_frame_timestamp;
60 (timestamp - first_frame_timestamp_).InMicroseconds() * 71 segment_.AddFrame(
61 base::Time::kNanosecondsPerMicrosecond, 72 reinterpret_cast<const uint8_t*>(encoded_data->data()),
62 is_key_frame); 73 encoded_data->size(),
74 video_muxer_args_[track_index].track_number,
75 timestamp_delta.InMicroseconds() * base::Time::kNanosecondsPerMicrosecond,
76 is_key_frame);
63 } 77 }
64 78
65 void WebmMuxer::AddVideoTrack(const gfx::Size& frame_size, double frame_rate) { 79 int WebmMuxer::GetNextVideoTrackIndex() {
80 return video_muxer_args_.size();
81 }
82
83 uint64 WebmMuxer::AddVideoTrack(
84 const gfx::Size& frame_size, double frame_rate) {
66 DCHECK(thread_checker_.CalledOnValidThread()); 85 DCHECK(thread_checker_.CalledOnValidThread());
67 DCHECK_EQ(track_index_, 0u) << "WebmMuxer can only be initialised once.";
68 86
69 segment_.Init(this); 87 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); 88 segment_.AddVideoTrack(frame_size.width(), frame_size.height(), 0);
79 DCHECK_GT(track_index_, 0u); 89 DCHECK_GT(track_num, 0u);
80 90
81 mkvmuxer::VideoTrack* const video_track = 91 mkvmuxer::VideoTrack* const video_track =
82 reinterpret_cast<mkvmuxer::VideoTrack*>( 92 reinterpret_cast<mkvmuxer::VideoTrack*>(
83 segment_.GetTrackByNumber(track_index_)); 93 segment_.GetTrackByNumber(track_num));
84 DCHECK(video_track); 94 DCHECK(video_track);
85 video_track->set_codec_id(mkvmuxer::Tracks::kVp8CodecId); 95 video_track->set_codec_id(mkvmuxer::Tracks::kVp8CodecId);
86 DCHECK_EQ(video_track->crop_right(), 0ull); 96 DCHECK_EQ(video_track->crop_right(), 0ull);
87 DCHECK_EQ(video_track->crop_left(), 0ull); 97 DCHECK_EQ(video_track->crop_left(), 0ull);
88 DCHECK_EQ(video_track->crop_top(), 0ull); 98 DCHECK_EQ(video_track->crop_top(), 0ull);
89 DCHECK_EQ(video_track->crop_bottom(), 0ull); 99 DCHECK_EQ(video_track->crop_bottom(), 0ull);
90 100
91 video_track->set_frame_rate(frame_rate); 101 video_track->set_frame_rate(frame_rate);
92 video_track->set_default_duration(base::Time::kNanosecondsPerSecond / 102 video_track->set_default_duration(base::Time::kNanosecondsPerSecond /
93 frame_rate); 103 frame_rate);
94 // Segment's timestamps should be in milliseconds, DCHECK it. See 104 // Segment's timestamps should be in milliseconds, DCHECK it. See
95 // http://www.webmproject.org/docs/container/#muxer-guidelines 105 // http://www.webmproject.org/docs/container/#muxer-guidelines
96 DCHECK_EQ(segment_.GetSegmentInfo()->timecode_scale(), 1000000ull); 106 DCHECK_EQ(segment_.GetSegmentInfo()->timecode_scale(), 1000000ull);
107
108 return track_num;
97 } 109 }
98 110
99 mkvmuxer::int32 WebmMuxer::Write(const void* buf, mkvmuxer::uint32 len) { 111 mkvmuxer::int32 WebmMuxer::Write(const void* buf, mkvmuxer::uint32 len) {
100 DCHECK(thread_checker_.CalledOnValidThread()); 112 DCHECK(thread_checker_.CalledOnValidThread());
101 DCHECK(buf); 113 DCHECK(buf);
102 write_data_callback_.Run(base::StringPiece(reinterpret_cast<const char*>(buf), 114 write_data_callback_.Run(base::StringPiece(reinterpret_cast<const char*>(buf),
103 len)); 115 len));
104 position_ += len; 116 position_ += len;
105 return 0; 117 return 0;
106 } 118 }
(...skipping 12 matching lines...) Expand all
119 } 131 }
120 132
121 void WebmMuxer::ElementStartNotify(mkvmuxer::uint64 element_id, 133 void WebmMuxer::ElementStartNotify(mkvmuxer::uint64 element_id,
122 mkvmuxer::int64 position) { 134 mkvmuxer::int64 position) {
123 // This method gets pinged before items are sent to |write_data_callback_|. 135 // This method gets pinged before items are sent to |write_data_callback_|.
124 DCHECK_GE(position, position_.ValueOrDefault(0)) 136 DCHECK_GE(position, position_.ValueOrDefault(0))
125 << "Can't go back in a live WebM stream."; 137 << "Can't go back in a live WebM stream.";
126 } 138 }
127 139
128 } // namespace media 140 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698