OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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/base/video_frame.h" | 5 #include "media/base/video_frame.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 return !coded_size.IsEmpty() && !visible_rect.IsEmpty() && | 188 return !coded_size.IsEmpty() && !visible_rect.IsEmpty() && |
189 !natural_size.IsEmpty(); | 189 !natural_size.IsEmpty(); |
190 } | 190 } |
191 | 191 |
192 // static | 192 // static |
193 scoped_refptr<VideoFrame> VideoFrame::CreateFrame(VideoPixelFormat format, | 193 scoped_refptr<VideoFrame> VideoFrame::CreateFrame(VideoPixelFormat format, |
194 const gfx::Size& coded_size, | 194 const gfx::Size& coded_size, |
195 const gfx::Rect& visible_rect, | 195 const gfx::Rect& visible_rect, |
196 const gfx::Size& natural_size, | 196 const gfx::Size& natural_size, |
197 base::TimeDelta timestamp) { | 197 base::TimeDelta timestamp) { |
198 if (!IsYuvPlanar(format)) { | 198 return CreateFrameInternal(format, coded_size, visible_rect, natural_size, |
199 NOTIMPLEMENTED(); | 199 timestamp, false); |
200 return nullptr; | |
201 } | |
202 | |
203 // Since we're creating a new YUV frame (and allocating memory for it | |
204 // ourselves), we can pad the requested |coded_size| if necessary if the | |
205 // request does not line up on sample boundaries. See discussion at | |
206 // http://crrev.com/1240833003 | |
207 const gfx::Size alignment = CommonAlignment(format); | |
208 const gfx::Size new_coded_size = | |
209 gfx::Size(RoundUp(coded_size.width(), alignment.width()), | |
210 RoundUp(coded_size.height(), alignment.height())); | |
211 DCHECK((new_coded_size.width() % alignment.width() == 0) && | |
212 (new_coded_size.height() % alignment.height() == 0)); | |
213 | |
214 const StorageType storage = STORAGE_OWNED_MEMORY; | |
215 if (!IsValidConfig(format, storage, new_coded_size, visible_rect, | |
216 natural_size)) { | |
217 DLOG(ERROR) << __FUNCTION__ << " Invalid config." | |
218 << ConfigToString(format, storage, coded_size, visible_rect, | |
219 natural_size); | |
220 return nullptr; | |
221 } | |
222 | |
223 scoped_refptr<VideoFrame> frame(new VideoFrame( | |
224 format, storage, new_coded_size, visible_rect, natural_size, timestamp)); | |
225 frame->AllocateYUV(); | |
226 return frame; | |
227 } | 200 } |
228 | 201 |
229 // static | 202 // static |
| 203 scoped_refptr<VideoFrame> VideoFrame::CreateZeroInitializedFrame( |
| 204 VideoPixelFormat format, |
| 205 const gfx::Size& coded_size, |
| 206 const gfx::Rect& visible_rect, |
| 207 const gfx::Size& natural_size, |
| 208 base::TimeDelta timestamp) { |
| 209 return CreateFrameInternal(format, coded_size, visible_rect, natural_size, |
| 210 timestamp, true); |
| 211 } |
| 212 |
| 213 // static |
230 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( | 214 scoped_refptr<VideoFrame> VideoFrame::WrapNativeTexture( |
231 VideoPixelFormat format, | 215 VideoPixelFormat format, |
232 const gpu::MailboxHolder& mailbox_holder, | 216 const gpu::MailboxHolder& mailbox_holder, |
233 const ReleaseMailboxCB& mailbox_holder_release_cb, | 217 const ReleaseMailboxCB& mailbox_holder_release_cb, |
234 const gfx::Size& coded_size, | 218 const gfx::Size& coded_size, |
235 const gfx::Rect& visible_rect, | 219 const gfx::Rect& visible_rect, |
236 const gfx::Size& natural_size, | 220 const gfx::Size& natural_size, |
237 base::TimeDelta timestamp) { | 221 base::TimeDelta timestamp) { |
238 if (format != PIXEL_FORMAT_ARGB && format != PIXEL_FORMAT_UYVY) { | 222 if (format != PIXEL_FORMAT_ARGB && format != PIXEL_FORMAT_UYVY) { |
239 DLOG(ERROR) << "Unsupported pixel format supported, got " | 223 DLOG(ERROR) << "Unsupported pixel format supported, got " |
(...skipping 650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 base::AutoLock locker(release_sync_point_lock_); | 874 base::AutoLock locker(release_sync_point_lock_); |
891 release_sync_point = release_sync_point_; | 875 release_sync_point = release_sync_point_; |
892 } | 876 } |
893 base::ResetAndReturn(&mailbox_holders_release_cb_).Run(release_sync_point); | 877 base::ResetAndReturn(&mailbox_holders_release_cb_).Run(release_sync_point); |
894 } | 878 } |
895 | 879 |
896 for (auto& callback : done_callbacks_) | 880 for (auto& callback : done_callbacks_) |
897 base::ResetAndReturn(&callback).Run(); | 881 base::ResetAndReturn(&callback).Run(); |
898 } | 882 } |
899 | 883 |
900 void VideoFrame::AllocateYUV() { | 884 // static |
| 885 scoped_refptr<VideoFrame> VideoFrame::CreateFrameInternal( |
| 886 VideoPixelFormat format, |
| 887 const gfx::Size& coded_size, |
| 888 const gfx::Rect& visible_rect, |
| 889 const gfx::Size& natural_size, |
| 890 base::TimeDelta timestamp, |
| 891 bool zero_initialize_memory) { |
| 892 if (!IsYuvPlanar(format)) { |
| 893 NOTIMPLEMENTED(); |
| 894 return nullptr; |
| 895 } |
| 896 |
| 897 // Since we're creating a new YUV frame (and allocating memory for it |
| 898 // ourselves), we can pad the requested |coded_size| if necessary if the |
| 899 // request does not line up on sample boundaries. See discussion at |
| 900 // http://crrev.com/1240833003 |
| 901 const gfx::Size alignment = CommonAlignment(format); |
| 902 const gfx::Size new_coded_size = |
| 903 gfx::Size(RoundUp(coded_size.width(), alignment.width()), |
| 904 RoundUp(coded_size.height(), alignment.height())); |
| 905 DCHECK((new_coded_size.width() % alignment.width() == 0) && |
| 906 (new_coded_size.height() % alignment.height() == 0)); |
| 907 |
| 908 const StorageType storage = STORAGE_OWNED_MEMORY; |
| 909 if (!IsValidConfig(format, storage, new_coded_size, visible_rect, |
| 910 natural_size)) { |
| 911 DLOG(ERROR) << __FUNCTION__ << " Invalid config." |
| 912 << ConfigToString(format, storage, coded_size, visible_rect, |
| 913 natural_size); |
| 914 return nullptr; |
| 915 } |
| 916 |
| 917 scoped_refptr<VideoFrame> frame(new VideoFrame( |
| 918 format, storage, new_coded_size, visible_rect, natural_size, timestamp)); |
| 919 frame->AllocateYUV(zero_initialize_memory); |
| 920 return frame; |
| 921 } |
| 922 |
| 923 void VideoFrame::AllocateYUV(bool zero_initialize_memory) { |
901 DCHECK_EQ(storage_type_, STORAGE_OWNED_MEMORY); | 924 DCHECK_EQ(storage_type_, STORAGE_OWNED_MEMORY); |
902 static_assert(0 == kYPlane, "y plane data must be index 0"); | 925 static_assert(0 == kYPlane, "y plane data must be index 0"); |
903 | 926 |
904 size_t data_size = 0; | 927 size_t data_size = 0; |
905 size_t offset[kMaxPlanes]; | 928 size_t offset[kMaxPlanes]; |
906 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) { | 929 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) { |
907 // The *2 in alignment for height is because some formats (e.g. h264) allow | 930 // The *2 in alignment for height is because some formats (e.g. h264) allow |
908 // interlaced coding, and then the size needs to be a multiple of two | 931 // interlaced coding, and then the size needs to be a multiple of two |
909 // macroblocks (vertically). See | 932 // macroblocks (vertically). See |
910 // libavcodec/utils.c:avcodec_align_dimensions2(). | 933 // libavcodec/utils.c:avcodec_align_dimensions2(). |
911 const size_t height = RoundUp(rows(plane), kFrameSizeAlignment * 2); | 934 const size_t height = RoundUp(rows(plane), kFrameSizeAlignment * 2); |
912 strides_[plane] = RoundUp(row_bytes(plane), kFrameSizeAlignment); | 935 strides_[plane] = RoundUp(row_bytes(plane), kFrameSizeAlignment); |
913 offset[plane] = data_size; | 936 offset[plane] = data_size; |
914 data_size += height * strides_[plane]; | 937 data_size += height * strides_[plane]; |
915 } | 938 } |
916 | 939 |
917 // The extra line of UV being allocated is because h264 chroma MC | 940 // The extra line of UV being allocated is because h264 chroma MC |
918 // overreads by one line in some cases, see libavcodec/utils.c: | 941 // overreads by one line in some cases, see libavcodec/utils.c: |
919 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: | 942 // avcodec_align_dimensions2() and libavcodec/x86/h264_chromamc.asm: |
920 // put_h264_chroma_mc4_ssse3(). | 943 // put_h264_chroma_mc4_ssse3(). |
921 DCHECK(IsValidPlane(kUPlane, format_)); | 944 DCHECK(IsValidPlane(kUPlane, format_)); |
922 data_size += strides_[kUPlane] + kFrameSizePadding; | 945 data_size += strides_[kUPlane] + kFrameSizePadding; |
923 | 946 |
924 uint8* data = reinterpret_cast<uint8*>( | 947 uint8* data = reinterpret_cast<uint8*>( |
925 base::AlignedAlloc(data_size, kFrameAddressAlignment)); | 948 base::AlignedAlloc(data_size, kFrameAddressAlignment)); |
| 949 if (zero_initialize_memory) |
| 950 memset(data, 0, data_size); |
926 | 951 |
927 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) | 952 for (size_t plane = 0; plane < NumPlanes(format_); ++plane) |
928 data_[plane] = data + offset[plane]; | 953 data_[plane] = data + offset[plane]; |
929 | 954 |
930 AddDestructionObserver(base::Bind(&base::AlignedFree, data)); | 955 AddDestructionObserver(base::Bind(&base::AlignedFree, data)); |
931 } | 956 } |
932 | 957 |
933 } // namespace media | 958 } // namespace media |
OLD | NEW |