OLD | NEW |
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/muxers/webm_muxer.h" | 5 #include "media/muxers/webm_muxer.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "media/base/audio_parameters.h" | 11 #include "media/base/audio_parameters.h" |
12 #include "media/base/limits.h" | 12 #include "media/base/limits.h" |
13 #include "media/base/video_frame.h" | 13 #include "media/base/video_frame.h" |
14 #include "media/filters/opus_constants.h" | 14 #include "media/filters/opus_constants.h" |
15 #include "ui/gfx/geometry/size.h" | |
16 | 15 |
17 namespace media { | 16 namespace media { |
18 | 17 |
19 namespace { | 18 namespace { |
20 | 19 |
21 void WriteOpusHeader(const media::AudioParameters& params, uint8_t* header) { | 20 void WriteOpusHeader(const media::AudioParameters& params, uint8_t* header) { |
22 // See https://wiki.xiph.org/OggOpus#ID_Header. | 21 // See https://wiki.xiph.org/OggOpus#ID_Header. |
23 // Set magic signature. | 22 // Set magic signature. |
24 std::string label = "OpusHead"; | 23 std::string label = "OpusHead"; |
25 memcpy(header + OPUS_EXTRADATA_LABEL_OFFSET, label.c_str(), label.size()); | 24 memcpy(header + OPUS_EXTRADATA_LABEL_OFFSET, label.c_str(), label.size()); |
(...skipping 24 matching lines...) Expand all Loading... |
50 // Set the actual stream map. | 49 // Set the actual stream map. |
51 for (int i = 0; i < params.channels(); ++i) { | 50 for (int i = 0; i < params.channels(); ++i) { |
52 header[OPUS_EXTRADATA_STREAM_MAP_OFFSET + i] = | 51 header[OPUS_EXTRADATA_STREAM_MAP_OFFSET + i] = |
53 kOpusVorbisChannelMap[params.channels() - 1][i]; | 52 kOpusVorbisChannelMap[params.channels() - 1][i]; |
54 } | 53 } |
55 } else { | 54 } else { |
56 header[OPUS_EXTRADATA_CHANNEL_MAPPING_OFFSET] = 0; | 55 header[OPUS_EXTRADATA_CHANNEL_MAPPING_OFFSET] = 0; |
57 } | 56 } |
58 } | 57 } |
59 | 58 |
60 static double GetFrameRate(const scoped_refptr<VideoFrame>& video_frame) { | 59 static double GetFrameRate(const WebmMuxer::VideoParameters& params) { |
61 const double kZeroFrameRate = 0.0; | 60 const double kZeroFrameRate = 0.0; |
62 const double kDefaultFrameRate = 30.0; | 61 const double kDefaultFrameRate = 30.0; |
63 | 62 |
64 double frame_rate = kDefaultFrameRate; | 63 double frame_rate = params.frame_rate; |
65 if (!video_frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE, | 64 if (frame_rate <= kZeroFrameRate || |
66 &frame_rate) || | |
67 frame_rate <= kZeroFrameRate || | |
68 frame_rate > media::limits::kMaxFramesPerSecond) { | 65 frame_rate > media::limits::kMaxFramesPerSecond) { |
69 frame_rate = kDefaultFrameRate; | 66 frame_rate = kDefaultFrameRate; |
70 } | 67 } |
71 return frame_rate; | 68 return frame_rate; |
72 } | 69 } |
73 | 70 |
74 static const char kH264CodecId[] = "V_MPEG4/ISO/AVC"; | 71 static const char kH264CodecId[] = "V_MPEG4/ISO/AVC"; |
75 | 72 |
76 static const char* MkvCodeIcForMediaVideoCodecId(VideoCodec video_codec) { | 73 static const char* MkvCodeIcForMediaVideoCodecId(VideoCodec video_codec) { |
77 switch (video_codec) { | 74 switch (video_codec) { |
78 case kCodecVP8: | 75 case kCodecVP8: |
79 return mkvmuxer::Tracks::kVp8CodecId; | 76 return mkvmuxer::Tracks::kVp8CodecId; |
80 case kCodecVP9: | 77 case kCodecVP9: |
81 return mkvmuxer::Tracks::kVp9CodecId; | 78 return mkvmuxer::Tracks::kVp9CodecId; |
82 case kCodecH264: | 79 case kCodecH264: |
83 return kH264CodecId; | 80 return kH264CodecId; |
84 default: | 81 default: |
85 NOTREACHED() << "Unsupported codec " << GetCodecName(video_codec); | 82 NOTREACHED() << "Unsupported codec " << GetCodecName(video_codec); |
86 return ""; | 83 return ""; |
87 } | 84 } |
88 } | 85 } |
89 | 86 |
90 } // anonymous namespace | 87 } // anonymous namespace |
91 | 88 |
| 89 WebmMuxer::VideoParameters::VideoParameters( |
| 90 scoped_refptr<media::VideoFrame> frame) { |
| 91 frame_size = frame->visible_rect().size(); |
| 92 frame_rate = 0.0; |
| 93 ignore_result(frame->metadata()->GetDouble(VideoFrameMetadata::FRAME_RATE, |
| 94 &frame_rate)); |
| 95 } |
| 96 |
| 97 WebmMuxer::VideoParameters::~VideoParameters() {} |
| 98 |
92 WebmMuxer::WebmMuxer(VideoCodec codec, | 99 WebmMuxer::WebmMuxer(VideoCodec codec, |
93 bool has_video, | 100 bool has_video, |
94 bool has_audio, | 101 bool has_audio, |
95 const WriteDataCB& write_data_callback) | 102 const WriteDataCB& write_data_callback) |
96 : video_codec_(codec), | 103 : video_codec_(codec), |
97 video_track_index_(0), | 104 video_track_index_(0), |
98 audio_track_index_(0), | 105 audio_track_index_(0), |
99 has_video_(has_video), | 106 has_video_(has_video), |
100 has_audio_(has_audio), | 107 has_audio_(has_audio), |
101 write_data_callback_(write_data_callback), | 108 write_data_callback_(write_data_callback), |
(...skipping 15 matching lines...) Expand all Loading... |
117 thread_checker_.DetachFromThread(); | 124 thread_checker_.DetachFromThread(); |
118 } | 125 } |
119 | 126 |
120 WebmMuxer::~WebmMuxer() { | 127 WebmMuxer::~WebmMuxer() { |
121 // No need to segment_.Finalize() since is not Seekable(), i.e. a live | 128 // No need to segment_.Finalize() since is not Seekable(), i.e. a live |
122 // stream, but is a good practice. | 129 // stream, but is a good practice. |
123 DCHECK(thread_checker_.CalledOnValidThread()); | 130 DCHECK(thread_checker_.CalledOnValidThread()); |
124 segment_.Finalize(); | 131 segment_.Finalize(); |
125 } | 132 } |
126 | 133 |
127 void WebmMuxer::OnEncodedVideo(const scoped_refptr<VideoFrame>& video_frame, | 134 void WebmMuxer::OnEncodedVideo(const VideoParameters& params, |
128 std::unique_ptr<std::string> encoded_data, | 135 std::unique_ptr<std::string> encoded_data, |
129 base::TimeTicks timestamp, | 136 base::TimeTicks timestamp, |
130 bool is_key_frame) { | 137 bool is_key_frame) { |
131 DVLOG(1) << __func__ << " - " << encoded_data->size() << "B"; | 138 DVLOG(1) << __func__ << " - " << encoded_data->size() << "B"; |
132 DCHECK(thread_checker_.CalledOnValidThread()); | 139 DCHECK(thread_checker_.CalledOnValidThread()); |
133 | 140 |
134 if (!video_track_index_) { | 141 if (!video_track_index_) { |
135 // |track_index_|, cannot be zero (!), initialize WebmMuxer in that case. | 142 // |track_index_|, cannot be zero (!), initialize WebmMuxer in that case. |
136 // http://www.matroska.org/technical/specs/index.html#Tracks | 143 // http://www.matroska.org/technical/specs/index.html#Tracks |
137 AddVideoTrack(video_frame->visible_rect().size(), | 144 AddVideoTrack(params.frame_size, GetFrameRate(params)); |
138 GetFrameRate(video_frame)); | |
139 if (first_frame_timestamp_video_.is_null()) | 145 if (first_frame_timestamp_video_.is_null()) |
140 first_frame_timestamp_video_ = timestamp; | 146 first_frame_timestamp_video_ = timestamp; |
141 } | 147 } |
142 | 148 |
143 // TODO(ajose): Support multiple tracks: http://crbug.com/528523 | 149 // TODO(ajose): Support multiple tracks: http://crbug.com/528523 |
144 if (has_audio_ && !audio_track_index_) { | 150 if (has_audio_ && !audio_track_index_) { |
145 DVLOG(1) << __func__ << ": delaying until audio track ready."; | 151 DVLOG(1) << __func__ << ": delaying until audio track ready."; |
146 if (is_key_frame) // Upon Key frame reception, empty the encoded queue. | 152 if (is_key_frame) // Upon Key frame reception, empty the encoded queue. |
147 encoded_frames_queue_.clear(); | 153 encoded_frames_queue_.clear(); |
148 | 154 |
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
325 | 331 |
326 WebmMuxer::EncodedVideoFrame::EncodedVideoFrame( | 332 WebmMuxer::EncodedVideoFrame::EncodedVideoFrame( |
327 std::unique_ptr<std::string> data, | 333 std::unique_ptr<std::string> data, |
328 base::TimeTicks timestamp, | 334 base::TimeTicks timestamp, |
329 bool is_keyframe) | 335 bool is_keyframe) |
330 : data(std::move(data)), timestamp(timestamp), is_keyframe(is_keyframe) {} | 336 : data(std::move(data)), timestamp(timestamp), is_keyframe(is_keyframe) {} |
331 | 337 |
332 WebmMuxer::EncodedVideoFrame::~EncodedVideoFrame() {} | 338 WebmMuxer::EncodedVideoFrame::~EncodedVideoFrame() {} |
333 | 339 |
334 } // namespace media | 340 } // namespace media |
OLD | NEW |