| Index: content/renderer/media/webrtc/video_destination_handler.cc
|
| diff --git a/content/renderer/media/webrtc/video_destination_handler.cc b/content/renderer/media/webrtc/video_destination_handler.cc
|
| index 160537165d7912e4c514f6d49272f9dd60d0adde..505d59c5ea84b6933113819a9cdf420013250f36 100644
|
| --- a/content/renderer/media/webrtc/video_destination_handler.cc
|
| +++ b/content/renderer/media/webrtc/video_destination_handler.cc
|
| @@ -41,6 +41,13 @@ class PpFrameWriter::FrameWriterDelegate
|
|
|
| private:
|
| friend class base::RefCountedThreadSafe<FrameWriterDelegate>;
|
| + // Endian in memory order, e.g. AXXX stands for uint8 pixel[4] = {A, x, x, x};
|
| + enum PixelEndian {
|
| + UNKNOWN,
|
| + AXXX,
|
| + XXXA,
|
| + };
|
| +
|
| virtual ~FrameWriterDelegate();
|
|
|
| void StartDeliverOnIO(const VideoCaptureDeliverFrameCB& frame_callback);
|
| @@ -52,9 +59,11 @@ class PpFrameWriter::FrameWriterDelegate
|
|
|
| scoped_refptr<base::MessageLoopProxy> io_message_loop_;
|
|
|
| - // |frame_pool_| and |new_frame_callback_| are only used on the IO-thread.
|
| + // |frame_pool_|, |new_frame_callback_| and |endian_| are only used on the
|
| + // IO-thread.
|
| media::VideoFramePool frame_pool_;
|
| VideoCaptureDeliverFrameCB new_frame_callback_;
|
| + PixelEndian endian_;
|
|
|
| // Used to DCHECK that we are called on the main render thread.
|
| base::ThreadChecker thread_checker_;
|
| @@ -62,7 +71,7 @@ class PpFrameWriter::FrameWriterDelegate
|
|
|
| PpFrameWriter::FrameWriterDelegate::FrameWriterDelegate(
|
| const scoped_refptr<base::MessageLoopProxy>& io_message_loop_proxy)
|
| - : io_message_loop_(io_message_loop_proxy) {
|
| + : io_message_loop_(io_message_loop_proxy), endian_(UNKNOWN) {
|
| }
|
|
|
| PpFrameWriter::FrameWriterDelegate::~FrameWriterDelegate() {
|
| @@ -101,6 +110,8 @@ void PpFrameWriter::FrameWriterDelegate::DeliverFrame(
|
| << "The image_data's mapped bitmap is NULL.";
|
| return;
|
| }
|
| + // We only support PP_IMAGEDATAFORMAT_BGRA_PREMUL at the moment.
|
| + DCHECK(image_data->format() == PP_IMAGEDATAFORMAT_BGRA_PREMUL);
|
| io_message_loop_->PostTaskAndReply(
|
| FROM_HERE,
|
| base::Bind(&FrameWriterDelegate::DeliverFrameOnIO, this,
|
| @@ -153,15 +164,46 @@ void PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO(
|
| MediaStreamVideoSource::kUnknownFrameRate,
|
| media::PIXEL_FORMAT_YV12);
|
|
|
| - libyuv::BGRAToI420(data,
|
| - stride,
|
| - new_frame->data(media::VideoFrame::kYPlane),
|
| - new_frame->stride(media::VideoFrame::kYPlane),
|
| - new_frame->data(media::VideoFrame::kUPlane),
|
| - new_frame->stride(media::VideoFrame::kUPlane),
|
| - new_frame->data(media::VideoFrame::kVPlane),
|
| - new_frame->stride(media::VideoFrame::kVPlane),
|
| - frame_size.width(), frame_size.height());
|
| + // TODO(magjed): Remove this and always use libyuv::ARGBToI420 when
|
| + // crbug/426020 is fixed.
|
| + // Due to a change in endianness, we try to determine it from the data.
|
| + // The alpha channel is always 255. It is unlikely for other color channels to
|
| + // be 255, so we will most likely break on the first few pixels in the first
|
| + // frame.
|
| + uint8* row_ptr = data;
|
| + // Note that we only do this if endian_ is still UNKNOWN.
|
| + for (int y = 0; y < height && endian_ == UNKNOWN; ++y) {
|
| + for (int x = 0; x < width; ++x) {
|
| + if (row_ptr[x * 4 + 0] != 255) { // First byte is not Alpha => XXXA.
|
| + endian_ = XXXA;
|
| + break;
|
| + }
|
| + if (row_ptr[x * 4 + 3] != 255) { // Fourth byte is not Alpha => AXXX.
|
| + endian_ = AXXX;
|
| + break;
|
| + }
|
| + }
|
| + row_ptr += stride;
|
| + }
|
| + if (endian_ == UNKNOWN) {
|
| + LOG(WARNING) << "PpFrameWriter::FrameWriterDelegate::DeliverFrameOnIO - "
|
| + << "Could not determine endianness.";
|
| + }
|
| + // libyuv specifies fourcc/channel ordering the same as webrtc. That is why
|
| + // the naming is reversed compared to PixelEndian and PP_ImageDataFormat which
|
| + // describes the memory layout from the lowest address to the highest.
|
| + const auto* xxxxToI420 =
|
| + (endian_ == AXXX) ? &libyuv::BGRAToI420 : &libyuv::ARGBToI420;
|
| + xxxxToI420(data,
|
| + stride,
|
| + new_frame->data(media::VideoFrame::kYPlane),
|
| + new_frame->stride(media::VideoFrame::kYPlane),
|
| + new_frame->data(media::VideoFrame::kUPlane),
|
| + new_frame->stride(media::VideoFrame::kUPlane),
|
| + new_frame->data(media::VideoFrame::kVPlane),
|
| + new_frame->stride(media::VideoFrame::kVPlane),
|
| + width,
|
| + height);
|
|
|
| // The local time when this frame is generated is unknown so give a null
|
| // value to |estimated_capture_time|.
|
|
|