blob: d8b66605dcfeb4c8d8135b997a80b9cd82d63835 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MEDIA_CAPTURE_VIDEO_MAC_SAMPLE_BUFFER_TRANSFORMER_MAC_H_
#define MEDIA_CAPTURE_VIDEO_MAC_SAMPLE_BUFFER_TRANSFORMER_MAC_H_
#import <CoreMedia/CoreMedia.h>
#import <CoreVideo/CoreVideo.h>
#include <vector>
#include "base/feature_list.h"
#include "base/mac/scoped_cftyperef.h"
#include "media/capture/capture_export.h"
#include "media/capture/video/mac/pixel_buffer_pool_mac.h"
#include "media/capture/video/mac/pixel_buffer_transferer_mac.h"
#include "ui/gfx/geometry/size.h"
namespace media {
// Capable of converting from any supported capture format (NV12, YUY2, UYVY and
// MJPEG) to NV12 or I420 and doing rescaling. This class can be configured to
// use VTPixelTransferSession (sometimes HW-accelerated) or third_party/libyuv
// (SW-only). The output is always an IOSurface-backed pixel buffer that comes
// from an internal pixel buffer pool.
class CAPTURE_EXPORT SampleBufferTransformer {
public:
enum class Transformer {
kNotConfigured,
// Supports (Any except MJPEG) -> (NV12, I420, ...)
kPixelBufferTransfer,
// Supports (Any) -> (NV12 or I420)
kLibyuv,
};
// TODO(https://crbug.com/1175763): Make determining the optimal Transformer
// an implementation detail determined at Transform()-time, making
// Reconfigure() only care about destination resolution and pixel format. Then
// make it possible to override this decision explicitly but only do that for
// testing and measurements purposes, not in default capturer integration.
static const Transformer kBestTransformerForPixelBufferToNv12Output;
static Transformer GetBestTransformerForNv12Output(
CMSampleBufferRef sample_buffer);
static std::unique_ptr<SampleBufferTransformer> Create();
~SampleBufferTransformer();
Transformer transformer() const;
OSType destination_pixel_format() const;
const gfx::Size& destination_size() const;
// Future calls to Transform() will output pixel buffers according to this
// configuration. Changing configuration will allocate a new buffer pool, but
// calling Reconfigure() multiple times with the same parameters is a NO-OP.
void Reconfigure(Transformer transformer,
OSType destination_pixel_format,
const gfx::Size& destination_size,
absl::optional<size_t> buffer_pool_size = absl::nullopt);
// Converts the input buffer to an IOSurface-backed pixel buffer according to
// current configurations. If no transformation is needed (input format is the
// same as the configured output format), the input pixel buffer is returned.
base::ScopedCFTypeRef<CVPixelBufferRef> Transform(
CVPixelBufferRef pixel_buffer);
base::ScopedCFTypeRef<CVPixelBufferRef> Transform(
CMSampleBufferRef sample_buffer);
private:
friend std::unique_ptr<SampleBufferTransformer>
std::make_unique<SampleBufferTransformer>();
SampleBufferTransformer();
// Sample buffers from the camera contain pixel buffers when an uncompressed
// pixel format is used (i.e. it's not MJPEG).
void TransformPixelBuffer(CVPixelBufferRef source_pixel_buffer,
CVPixelBufferRef destination_pixel_buffer);
// (Any uncompressed -> Any uncompressed)
void TransformPixelBufferWithPixelTransfer(
CVPixelBufferRef source_pixel_buffer,
CVPixelBufferRef destination_pixel_buffer);
// (Any uncompressed -> NV12 or I420)
void TransformPixelBufferWithLibyuv(
CVPixelBufferRef source_pixel_buffer,
CVPixelBufferRef destination_pixel_buffer);
void TransformPixelBufferWithLibyuvFromAnyToI420(
CVPixelBufferRef source_pixel_buffer,
CVPixelBufferRef destination_pixel_buffer);
void TransformPixelBufferWithLibyuvFromAnyToNV12(
CVPixelBufferRef source_pixel_buffer,
CVPixelBufferRef destination_pixel_buffer);
// Sample buffers from the camera contain byte buffers when MJPEG is used.
bool TransformSampleBuffer(CMSampleBufferRef source_sample_buffer,
CVPixelBufferRef destination_pixel_buffer);
bool TransformSampleBufferFromMjpegToI420(
uint8_t* source_buffer_data_base_address,
size_t source_buffer_data_size,
size_t source_width,
size_t source_height,
CVPixelBufferRef destination_pixel_buffer);
bool TransformSampleBufferFromMjpegToNV12(
uint8_t* source_buffer_data_base_address,
size_t source_buffer_data_size,
size_t source_width,
size_t source_height,
CVPixelBufferRef destination_pixel_buffer);
Transformer transformer_;
OSType destination_pixel_format_;
gfx::Size destination_size_;
std::unique_ptr<PixelBufferPool> destination_pixel_buffer_pool_;
// For kPixelBufferTransfer.
std::unique_ptr<PixelBufferTransferer> pixel_buffer_transferer_;
// For kLibyuv in cases where an intermediate buffer is needed.
std::vector<uint8_t> intermediate_i420_buffer_;
std::vector<uint8_t> intermediate_nv12_buffer_;
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_MAC_SAMPLE_BUFFER_TRANSFORMER_MAC_H_