| 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 "content/renderer/media_recorder/video_track_recorder.h" | 5 #include "content/renderer/media_recorder/video_track_recorder.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 #if BUILDFLAG(RTC_USE_H264) | 32 #if BUILDFLAG(RTC_USE_H264) |
| 33 #include "content/renderer/media_recorder/h264_encoder.h" | 33 #include "content/renderer/media_recorder/h264_encoder.h" |
| 34 #endif // #if BUILDFLAG(RTC_USE_H264) | 34 #endif // #if BUILDFLAG(RTC_USE_H264) |
| 35 | 35 |
| 36 using media::VideoFrame; | 36 using media::VideoFrame; |
| 37 using video_track_recorder::kVEAEncoderMinResolutionWidth; | 37 using video_track_recorder::kVEAEncoderMinResolutionWidth; |
| 38 using video_track_recorder::kVEAEncoderMinResolutionHeight; | 38 using video_track_recorder::kVEAEncoderMinResolutionHeight; |
| 39 | 39 |
| 40 namespace content { | 40 namespace content { |
| 41 | 41 |
| 42 libyuv::RotationMode MediaVideoRotationToRotationMode( |
| 43 media::VideoRotation rotation) { |
| 44 switch (rotation) { |
| 45 case media::VIDEO_ROTATION_0: |
| 46 return libyuv::kRotate0; |
| 47 case media::VIDEO_ROTATION_90: |
| 48 return libyuv::kRotate90; |
| 49 case media::VIDEO_ROTATION_180: |
| 50 return libyuv::kRotate180; |
| 51 case media::VIDEO_ROTATION_270: |
| 52 return libyuv::kRotate270; |
| 53 } |
| 54 NOTREACHED() << rotation; |
| 55 return libyuv::kRotate0; |
| 56 } |
| 57 |
| 42 namespace { | 58 namespace { |
| 43 | 59 |
| 44 using CodecId = VideoTrackRecorder::CodecId; | 60 using CodecId = VideoTrackRecorder::CodecId; |
| 45 | 61 |
| 46 static const struct { | 62 static const struct { |
| 47 CodecId codec_id; | 63 CodecId codec_id; |
| 48 media::VideoCodecProfile min_profile; | 64 media::VideoCodecProfile min_profile; |
| 49 media::VideoCodecProfile max_profile; | 65 media::VideoCodecProfile max_profile; |
| 50 } kPreferredCodecIdAndVEAProfiles[] = { | 66 } kPreferredCodecIdAndVEAProfiles[] = { |
| 51 {CodecId::VP8, media::VP8PROFILE_MIN, media::VP8PROFILE_MAX}, | 67 {CodecId::VP8, media::VP8PROFILE_MIN, media::VP8PROFILE_MAX}, |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 // Send black frames (yuv = {0, 127, 127}). | 228 // Send black frames (yuv = {0, 127, 127}). |
| 213 frame = media::VideoFrame::CreateColorFrame( | 229 frame = media::VideoFrame::CreateColorFrame( |
| 214 video_frame->visible_rect().size(), 0u, 0x80, 0x80, | 230 video_frame->visible_rect().size(), 0u, 0x80, 0x80, |
| 215 video_frame->timestamp()); | 231 video_frame->timestamp()); |
| 216 } else { | 232 } else { |
| 217 // Accelerated decoders produce ARGB/ABGR texture-backed frames (see | 233 // Accelerated decoders produce ARGB/ABGR texture-backed frames (see |
| 218 // https://crbug.com/585242), fetch them using a SkCanvasVideoRenderer. | 234 // https://crbug.com/585242), fetch them using a SkCanvasVideoRenderer. |
| 219 DCHECK(video_frame->HasTextures()); | 235 DCHECK(video_frame->HasTextures()); |
| 220 DCHECK_EQ(media::PIXEL_FORMAT_ARGB, video_frame->format()); | 236 DCHECK_EQ(media::PIXEL_FORMAT_ARGB, video_frame->format()); |
| 221 | 237 |
| 238 const gfx::Size& old_visible_size = video_frame->visible_rect().size(); |
| 239 gfx::Size new_visible_size = old_visible_size; |
| 240 |
| 241 media::VideoRotation video_rotation = media::VIDEO_ROTATION_0; |
| 242 if (video_frame->metadata()->GetRotation( |
| 243 media::VideoFrameMetadata::ROTATION, &video_rotation) && |
| 244 (video_rotation == media::VIDEO_ROTATION_90 || |
| 245 video_rotation == media::VIDEO_ROTATION_270)) { |
| 246 new_visible_size.SetSize(old_visible_size.height(), |
| 247 old_visible_size.width()); |
| 248 } |
| 249 |
| 222 frame = media::VideoFrame::CreateFrame( | 250 frame = media::VideoFrame::CreateFrame( |
| 223 media::PIXEL_FORMAT_I420, video_frame->coded_size(), | 251 media::PIXEL_FORMAT_I420, new_visible_size, gfx::Rect(new_visible_size), |
| 224 video_frame->visible_rect(), video_frame->natural_size(), | 252 new_visible_size, video_frame->timestamp()); |
| 225 video_frame->timestamp()); | |
| 226 | 253 |
| 227 const SkImageInfo info = SkImageInfo::MakeN32( | 254 const SkImageInfo info = SkImageInfo::MakeN32( |
| 228 frame->visible_rect().width(), frame->visible_rect().height(), | 255 frame->visible_rect().width(), frame->visible_rect().height(), |
| 229 kOpaque_SkAlphaType); | 256 kOpaque_SkAlphaType); |
| 230 | 257 |
| 231 // Create |surface_| if it doesn't exist or incoming resolution has changed. | 258 // Create |surface_| if it doesn't exist or incoming resolution has changed. |
| 232 if (!canvas_ || canvas_->imageInfo().width() != info.width() || | 259 if (!canvas_ || canvas_->imageInfo().width() != info.width() || |
| 233 canvas_->imageInfo().height() != info.height()) { | 260 canvas_->imageInfo().height() != info.height()) { |
| 234 bitmap_.allocPixels(info); | 261 bitmap_.allocPixels(info); |
| 235 canvas_ = base::MakeUnique<cc::SkiaPaintCanvas>(bitmap_); | 262 canvas_ = base::MakeUnique<cc::SkiaPaintCanvas>(bitmap_); |
| 236 } | 263 } |
| 237 if (!video_renderer_) | 264 if (!video_renderer_) |
| 238 video_renderer_.reset(new media::SkCanvasVideoRenderer); | 265 video_renderer_.reset(new media::SkCanvasVideoRenderer); |
| 239 | 266 |
| 240 DCHECK(context_provider->ContextGL()); | 267 DCHECK(context_provider->ContextGL()); |
| 241 video_renderer_->Copy(video_frame.get(), canvas_.get(), | 268 video_renderer_->Copy(video_frame.get(), canvas_.get(), |
| 242 media::Context3D(context_provider->ContextGL(), | 269 media::Context3D(context_provider->ContextGL(), |
| 243 context_provider->GrContext())); | 270 context_provider->GrContext())); |
| 244 | 271 |
| 245 SkPixmap pixmap; | 272 SkPixmap pixmap; |
| 246 if (!bitmap_.peekPixels(&pixmap)) { | 273 if (!bitmap_.peekPixels(&pixmap)) { |
| 247 DLOG(ERROR) << "Error trying to map PaintSurface's pixels"; | 274 DLOG(ERROR) << "Error trying to map PaintSurface's pixels"; |
| 248 return; | 275 return; |
| 249 } | 276 } |
| 250 // TODO(mcasas): Use the incoming frame's rotation when | 277 |
| 251 // https://bugs.chromium.org/p/webrtc/issues/detail?id=6069 is closed. | |
| 252 const libyuv::RotationMode source_rotation = libyuv::kRotate0; | |
| 253 const uint32 source_pixel_format = | 278 const uint32 source_pixel_format = |
| 254 (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR | 279 (kN32_SkColorType == kRGBA_8888_SkColorType) ? libyuv::FOURCC_ABGR |
| 255 : libyuv::FOURCC_ARGB; | 280 : libyuv::FOURCC_ARGB; |
| 256 if (libyuv::ConvertToI420(static_cast<uint8*>(pixmap.writable_addr()), | 281 if (libyuv::ConvertToI420( |
| 257 pixmap.getSafeSize(), | 282 static_cast<uint8*>(pixmap.writable_addr()), pixmap.getSafeSize(), |
| 258 frame->visible_data(media::VideoFrame::kYPlane), | 283 frame->visible_data(media::VideoFrame::kYPlane), |
| 259 frame->stride(media::VideoFrame::kYPlane), | 284 frame->stride(media::VideoFrame::kYPlane), |
| 260 frame->visible_data(media::VideoFrame::kUPlane), | 285 frame->visible_data(media::VideoFrame::kUPlane), |
| 261 frame->stride(media::VideoFrame::kUPlane), | 286 frame->stride(media::VideoFrame::kUPlane), |
| 262 frame->visible_data(media::VideoFrame::kVPlane), | 287 frame->visible_data(media::VideoFrame::kVPlane), |
| 263 frame->stride(media::VideoFrame::kVPlane), | 288 frame->stride(media::VideoFrame::kVPlane), 0 /* crop_x */, |
| 264 0 /* crop_x */, 0 /* crop_y */, | 289 0 /* crop_y */, pixmap.width(), pixmap.height(), |
| 265 pixmap.width(), pixmap.height(), | 290 old_visible_size.width(), old_visible_size.height(), |
| 266 frame->visible_rect().width(), | 291 MediaVideoRotationToRotationMode(video_rotation), |
| 267 frame->visible_rect().height(), | 292 source_pixel_format) != 0) { |
| 268 source_rotation, | |
| 269 source_pixel_format) != 0) { | |
| 270 DLOG(ERROR) << "Error converting frame to I420"; | 293 DLOG(ERROR) << "Error converting frame to I420"; |
| 271 return; | 294 return; |
| 272 } | 295 } |
| 273 } | 296 } |
| 274 | 297 |
| 275 encoding_task_runner_->PostTask( | 298 encoding_task_runner_->PostTask( |
| 276 FROM_HERE, base::Bind(&Encoder::EncodeOnEncodingTaskRunner, this, frame, | 299 FROM_HERE, base::Bind(&Encoder::EncodeOnEncodingTaskRunner, this, frame, |
| 277 capture_timestamp)); | 300 capture_timestamp)); |
| 278 } | 301 } |
| 279 | 302 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 MediaStreamVideoSink::DisconnectFromTrack(); | 458 MediaStreamVideoSink::DisconnectFromTrack(); |
| 436 encoder_ = nullptr; | 459 encoder_ = nullptr; |
| 437 MediaStreamVideoSink::ConnectToTrack( | 460 MediaStreamVideoSink::ConnectToTrack( |
| 438 track_, | 461 track_, |
| 439 media::BindToCurrentLoop(base::Bind(initialize_encoder_callback_, | 462 media::BindToCurrentLoop(base::Bind(initialize_encoder_callback_, |
| 440 false /*allow_vea_encoder*/)), | 463 false /*allow_vea_encoder*/)), |
| 441 false); | 464 false); |
| 442 } | 465 } |
| 443 | 466 |
| 444 } // namespace content | 467 } // namespace content |
| OLD | NEW |