content/media/fmp4/demuxer/video_util.cc

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include "mp4_demuxer/video_util.h"
     7 #include <cmath>
     9 namespace mp4_demuxer {
    11 IntSize GetNaturalSize(const IntSize& visible_size,
    12                        int aspect_ratio_numerator,
    13                        int aspect_ratio_denominator) {
    14   if (aspect_ratio_denominator == 0 ||
    15       aspect_ratio_numerator < 0 ||
    16       aspect_ratio_denominator < 0)
    17     return IntSize();
    19   double aspect_ratio = aspect_ratio_numerator /
    20       static_cast<double>(aspect_ratio_denominator);
    22   int width = floor(visible_size.width() * aspect_ratio + 0.5);
    23   int height = visible_size.height();
    25   // An even width makes things easier for YV12 and appears to be the behavior
    26   // expected by WebKit layout tests.
    27   return IntSize(width & ~1, height);
    28 }
    30 /*
    31 void CopyPlane(size_t plane, const uint8_t* source, int stride, int rows,
    32                VideoFrame* frame) {
    33   uint8_t* dest = frame->data(plane);
    34   int dest_stride = frame->stride(plane);
    36   // Clamp in case source frame has smaller stride.
    37   int bytes_to_copy_per_row = std::min(frame->row_bytes(plane), stride);
    39   // Clamp in case source frame has smaller height.
    40   int rows_to_copy = std::min(frame->rows(plane), rows);
    42   // Copy!
    43   for (int row = 0; row < rows_to_copy; ++row) {
    44     memcpy(dest, source, bytes_to_copy_per_row);
    45     source += stride;
    46     dest += dest_stride;
    47   }
    48 }
    50 void CopyYPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
    51   CopyPlane(VideoFrame::kYPlane, source, stride, rows, frame);
    52 }
    54 void CopyUPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
    55   CopyPlane(VideoFrame::kUPlane, source, stride, rows, frame);
    56 }
    58 void CopyVPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
    59   CopyPlane(VideoFrame::kVPlane, source, stride, rows, frame);
    60 }
    62 void CopyAPlane(const uint8_t* source, int stride, int rows, VideoFrame* frame) {
    63   CopyPlane(VideoFrame::kAPlane, source, stride, rows, frame);
    64 }
    66 void MakeOpaqueAPlane(int stride, int rows, VideoFrame* frame) {
    67   int rows_to_clear = std::min(frame->rows(VideoFrame::kAPlane), rows);
    68   memset(frame->data(VideoFrame::kAPlane), 255,
    69          frame->stride(VideoFrame::kAPlane) * rows_to_clear);
    70 }
    72 void FillYUV(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v) {
    73   // Fill the Y plane.
    74   uint8_t* y_plane = frame->data(VideoFrame::kYPlane);
    75   int y_rows = frame->rows(VideoFrame::kYPlane);
    76   int y_row_bytes = frame->row_bytes(VideoFrame::kYPlane);
    77   for (int i = 0; i < y_rows; ++i) {
    78     memset(y_plane, y, y_row_bytes);
    79     y_plane += frame->stride(VideoFrame::kYPlane);
    80   }
    82   // Fill the U and V planes.
    83   uint8_t* u_plane = frame->data(VideoFrame::kUPlane);
    84   uint8_t* v_plane = frame->data(VideoFrame::kVPlane);
    85   int uv_rows = frame->rows(VideoFrame::kUPlane);
    86   int u_row_bytes = frame->row_bytes(VideoFrame::kUPlane);
    87   int v_row_bytes = frame->row_bytes(VideoFrame::kVPlane);
    88   for (int i = 0; i < uv_rows; ++i) {
    89     memset(u_plane, u, u_row_bytes);
    90     memset(v_plane, v, v_row_bytes);
    91     u_plane += frame->stride(VideoFrame::kUPlane);
    92     v_plane += frame->stride(VideoFrame::kVPlane);
    93   }
    94 }
    96 static void LetterboxPlane(VideoFrame* frame,
    97                            int plane,
    98                            const gfx::Rect& view_area,
    99                            uint8_t fill_byte) {
   100   uint8_t* ptr = frame->data(plane);
   101   const int rows = frame->rows(plane);
   102   const int row_bytes = frame->row_bytes(plane);
   103   const int stride = frame->stride(plane);
   105   CHECK_GE(stride, row_bytes);
   106   CHECK_GE(view_area.x(), 0);
   107   CHECK_GE(view_area.y(), 0);
   108   CHECK_LE(view_area.right(), row_bytes);
   109   CHECK_LE(view_area.bottom(), rows);
   111   int y = 0;
   112   for (; y < view_area.y(); y++) {
   113     memset(ptr, fill_byte, row_bytes);
   114     ptr += stride;
   115   }
   116   if (view_area.width() < row_bytes) {
   117     for (; y < view_area.bottom(); y++) {
   118       if (view_area.x() > 0) {
   119         memset(ptr, fill_byte, view_area.x());
   120       }
   121       if (view_area.right() < row_bytes) {
   122         memset(ptr + view_area.right(),
   123                fill_byte,
   124                row_bytes - view_area.right());
   125       }
   126       ptr += stride;
   127     }
   128   } else {
   129     y += view_area.height();
   130     ptr += stride * view_area.height();
   131   }
   132   for (; y < rows; y++) {
   133     memset(ptr, fill_byte, row_bytes);
   134     ptr += stride;
   135   }
   136 }
   138 void LetterboxYUV(VideoFrame* frame, const gfx::Rect& view_area) {
   139   DCHECK(!(view_area.x() & 1));
   140   DCHECK(!(view_area.y() & 1));
   141   DCHECK(!(view_area.width() & 1));
   142   DCHECK(!(view_area.height() & 1));
   143   DCHECK_EQ(frame->format(), VideoFrame::YV12);
   144   LetterboxPlane(frame, VideoFrame::kYPlane, view_area, 0x00);
   145   gfx::Rect half_view_area(view_area.x() / 2,
   146                            view_area.y() / 2,
   147                            view_area.width() / 2,
   148                            view_area.height() / 2);
   149   LetterboxPlane(frame, VideoFrame::kUPlane, half_view_area, 0x80);
   150   LetterboxPlane(frame, VideoFrame::kVPlane, half_view_area, 0x80);
   151 }
   153 void RotatePlaneByPixels(
   154     const uint8_t* src,
   155     uint8_t* dest,
   156     int width,
   157     int height,
   158     int rotation,  // Clockwise.
   159     bool flip_vert,
   160     bool flip_horiz) {
   161   DCHECK((width > 0) && (height > 0) &&
   162          ((width & 1) == 0) && ((height & 1) == 0) &&
   163          (rotation >= 0) && (rotation < 360) && (rotation % 90 == 0));
   165   // Consolidate cases. Only 0 and 90 are left.
   166   if (rotation == 180 || rotation == 270) {
   167     rotation -= 180;
   168     flip_vert = !flip_vert;
   169     flip_horiz = !flip_horiz;
   170   }
   172   int num_rows = height;
   173   int num_cols = width;
   174   int src_stride = width;
   175   // During pixel copying, the corresponding incremental of dest pointer
   176   // when src pointer moves to next row.
   177   int dest_row_step = width;
   178   // During pixel copying, the corresponding incremental of dest pointer
   179   // when src pointer moves to next column.
   180   int dest_col_step = 1;
   182   if (rotation == 0) {
   183     if (flip_horiz) {
   184       // Use pixel copying.
   185       dest_col_step = -1;
   186       if (flip_vert) {
   187         // Rotation 180.
   188         dest_row_step = -width;
   189         dest += height * width - 1;
   190       } else {
   191         dest += width - 1;
   192       }
   193     } else {
   194       if (flip_vert) {
   195         // Fast copy by rows.
   196         dest += width * (height - 1);
   197         for (int row = 0; row < height; ++row) {
   198           memcpy(dest, src, width);
   199           src += width;
   200           dest -= width;
   201         }
   202       } else {
   203         memcpy(dest, src, width * height);
   204       }
   205       return;
   206     }
   207   } else if (rotation == 90) {
   208     int offset;
   209     if (width > height) {
   210       offset = (width - height) / 2;
   211       src += offset;
   212       num_rows = num_cols = height;
   213     } else {
   214       offset = (height - width) / 2;
   215       src += width * offset;
   216       num_rows = num_cols = width;
   217     }
   219     dest_col_step = (flip_vert ? -width : width);
   220     dest_row_step = (flip_horiz ? 1 : -1);
   221     if (flip_horiz) {
   222       if (flip_vert) {
   223         dest += (width > height ? width * (height - 1) + offset :
   224                                   width * (height - offset - 1));
   225       } else {
   226         dest += (width > height ? offset : width * offset);
   227       }
   228     } else {
   229       if (flip_vert) {
   230         dest += (width > height ?  width * height - offset - 1 :
   231                                    width * (height - offset) - 1);
   232       } else {
   233         dest += (width > height ? width - offset - 1 :
   234                                   width * (offset + 1) - 1);
   235       }
   236     }
   237   } else {
   238     NOTREACHED();
   239   }
   241   // Copy pixels.
   242   for (int row = 0; row < num_rows; ++row) {
   243     const uint8_t* src_ptr = src;
   244     uint8_t* dest_ptr = dest;
   245     for (int col = 0; col < num_cols; ++col) {
   246       *dest_ptr = *src_ptr++;
   247       dest_ptr += dest_col_step;
   248     }
   249     src += src_stride;
   250     dest += dest_row_step;
   251   }
   252 }
   254 gfx::Rect ComputeLetterboxRegion(const gfx::Rect& bounds,
   255                                  const IntSize& content) {
   256   int64_t x = static_cast<int64_t>(content.width()) * bounds.height();
   257   int64_t y = static_cast<int64_t>(content.height()) * bounds.width();
   259   IntSize letterbox(bounds.width(), bounds.height());
   260   if (y < x)
   261     letterbox.set_height(static_cast<int>(y / content.width()));
   262   else
   263     letterbox.set_width(static_cast<int>(x / content.height()));
   264   gfx::Rect result = bounds;
   265   result.ClampToCenteredSize(letterbox);
   266   return result;
   267 }
   269 void CopyRGBToVideoFrame(const uint8_t* source,
   270                          int stride,
   271                          const gfx::Rect& region_in_frame,
   272                          VideoFrame* frame) {
   273   const int kY = VideoFrame::kYPlane;
   274   const int kU = VideoFrame::kUPlane;
   275   const int kV = VideoFrame::kVPlane;
   276   CHECK_EQ(frame->stride(kU), frame->stride(kV));
   277   const int uv_stride = frame->stride(kU);
   279   if (region_in_frame != gfx::Rect(frame->coded_size())) {
   280     LetterboxYUV(frame, region_in_frame);
   281   }
   283   const int y_offset = region_in_frame.x()
   284                      + (region_in_frame.y() * frame->stride(kY));
   285   const int uv_offset = region_in_frame.x() / 2
   286                       + (region_in_frame.y() / 2 * uv_stride);
   288   ConvertRGB32ToYUV(source,
   289                     frame->data(kY) + y_offset,
   290                     frame->data(kU) + uv_offset,
   291                     frame->data(kV) + uv_offset,
   292                     region_in_frame.width(),
   293                     region_in_frame.height(),
   294                     stride,
   295                     frame->stride(kY),
   296                     uv_stride);
   297 }
   298 */
   299 }  // namespace mp4_demuxer

mercurial