Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Unified Diff: webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoDecoderH264.mm

Issue 2987413002: ObjC: Implement HW codecs in ObjC instead of C++ (Closed)
Patch Set: Move RTCH264PacketizationMode to RTCVideoCodec.h Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoDecoderH264.mm
diff --git a/webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.mm b/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoDecoderH264.mm
similarity index 38%
rename from webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.mm
rename to webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoDecoderH264.mm
index a8da8091d9f9a67cd90852c4df077870e0d51781..f657f9c2f12b68b1d1e95adf6370f418fb2655de 100644
--- a/webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.mm
+++ b/webrtc/sdk/objc/Framework/Classes/VideoToolbox/RTCVideoDecoderH264.mm
@@ -9,93 +9,80 @@
*
*/
-#include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/decoder.h"
+#import "WebRTC/RTCVideoCodecH264.h"
-#include <memory>
+#import <VideoToolbox/VideoToolbox.h>
-#include "libyuv/convert.h"
-#include "webrtc/api/video/video_frame.h"
-#include "webrtc/common_video/include/video_frame.h"
+#include "webrtc/modules/video_coding/include/video_error_codes.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/logging.h"
-#include "webrtc/sdk/objc/Framework/Classes/Video/objc_frame_buffer.h"
+#include "webrtc/rtc_base/timeutils.h"
#include "webrtc/sdk/objc/Framework/Classes/VideoToolbox/nalu_rewriter.h"
+#import "WebRTC/RTCVideoFrame.h"
#import "WebRTC/RTCVideoFrameBuffer.h"
+#import "helpers.h"
#if defined(WEBRTC_IOS)
#import "Common/RTCUIApplicationStatusObserver.h"
#endif
-namespace webrtc {
-namespace {
-
-static const int64_t kMsPerSec = 1000;
-
-// Convenience function for creating a dictionary.
-inline CFDictionaryRef CreateCFDictionary(CFTypeRef* keys,
- CFTypeRef* values,
- size_t size) {
- return CFDictionaryCreate(nullptr, keys, values, size,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
-}
-
// Struct that we pass to the decoder per frame to decode. We receive it again
// in the decoder callback.
-struct FrameDecodeParams {
- FrameDecodeParams(DecodedImageCallback* cb, int64_t ts)
- : callback(cb), timestamp(ts) {}
- DecodedImageCallback* callback;
+struct RTCFrameDecodeParams {
+ RTCFrameDecodeParams(RTCVideoDecoderCallback cb, int64_t ts) : callback(cb), timestamp(ts) {}
+ RTCVideoDecoderCallback callback;
int64_t timestamp;
};
// This is the callback function that VideoToolbox calls when decode is
// complete.
-void VTDecompressionOutputCallback(void* decoder,
- void* params,
- OSStatus status,
- VTDecodeInfoFlags info_flags,
- CVImageBufferRef image_buffer,
- CMTime timestamp,
- CMTime duration) {
- std::unique_ptr<FrameDecodeParams> decode_params(
- reinterpret_cast<FrameDecodeParams*>(params));
+void decompressionOutputCallback(void *decoder,
+ void *params,
+ OSStatus status,
+ VTDecodeInfoFlags infoFlags,
+ CVImageBufferRef imageBuffer,
+ CMTime timestamp,
+ CMTime duration) {
+ std::unique_ptr<RTCFrameDecodeParams> decodeParams(
+ reinterpret_cast<RTCFrameDecodeParams *>(params));
if (status != noErr) {
LOG(LS_ERROR) << "Failed to decode frame. Status: " << status;
return;
}
// TODO(tkchin): Handle CVO properly.
- rtc::scoped_refptr<VideoFrameBuffer> buffer = new rtc::RefCountedObject<ObjCFrameBuffer>(
- [[RTCCVPixelBuffer alloc] initWithPixelBuffer:image_buffer]);
- VideoFrame decoded_frame(buffer, decode_params->timestamp,
- CMTimeGetSeconds(timestamp) * kMsPerSec,
- kVideoRotation_0);
- decode_params->callback->Decoded(decoded_frame);
+ RTCCVPixelBuffer *frameBuffer = [[RTCCVPixelBuffer alloc] initWithPixelBuffer:imageBuffer];
+ RTCVideoFrame *decodedFrame =
+ [[RTCVideoFrame alloc] initWithBuffer:frameBuffer
+ rotation:RTCVideoRotation_0
+ timeStampNs:CMTimeGetSeconds(timestamp) * rtc::kNumNanosecsPerSec];
+ decodedFrame.timeStamp = decodeParams->timestamp;
+ decodeParams->callback(decodedFrame);
}
-} // namespace
-
-H264VideoToolboxDecoder::H264VideoToolboxDecoder()
- : callback_(nullptr), video_format_(nullptr), decompression_session_(nullptr) {}
+// Decoder.
+@implementation RTCVideoDecoderH264 {
+ CMVideoFormatDescriptionRef _videoFormat;
+ VTDecompressionSessionRef _decompressionSession;
+ RTCVideoDecoderCallback _callback;
+}
-H264VideoToolboxDecoder::~H264VideoToolboxDecoder() {
- DestroyDecompressionSession();
- SetVideoFormat(nullptr);
+- (void)dealloc {
+ [self destroyDecompressionSession];
+ [self setVideoFormat:nullptr];
}
-int H264VideoToolboxDecoder::InitDecode(const VideoCodec* video_codec,
- int number_of_cores) {
+- (NSInteger)startDecodeWithSettings:(RTCVideoEncoderSettings *)settings
+ numberOfCores:(int)numberOfCores {
return WEBRTC_VIDEO_CODEC_OK;
}
-int H264VideoToolboxDecoder::Decode(
- const EncodedImage& input_image,
- bool missing_frames,
- const RTPFragmentationHeader* fragmentation,
- const CodecSpecificInfo* codec_specific_info,
- int64_t render_time_ms) {
- RTC_DCHECK(input_image._buffer);
+- (NSInteger)decode:(RTCEncodedImage *)inputImage
+ missingFrames:(BOOL)missingFrames
+ fragmentationHeader:(RTCRtpFragmentationHeader *)fragmentationHeader
+ codecSpecificInfo:(__nullable id<RTCCodecSpecificInfo>)info
+ renderTimeMs:(int64_t)renderTimeMs {
+ RTC_DCHECK(inputImage.buffer);
#if defined(WEBRTC_IOS)
if (![[RTCUIApplicationStatusObserver sharedInstance] isApplicationActive]) {
@@ -103,26 +90,26 @@ int H264VideoToolboxDecoder::Decode(
// hardware decoder has been invalidated by the OS.
// Reset video format so that we won't process frames until the next
// keyframe.
- SetVideoFormat(nullptr);
+ [self setVideoFormat:nullptr];
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
}
#endif
- CMVideoFormatDescriptionRef input_format = nullptr;
- if (H264AnnexBBufferHasVideoFormatDescription(input_image._buffer,
- input_image._length)) {
- input_format = CreateVideoFormatDescription(input_image._buffer,
- input_image._length);
- if (input_format) {
+ CMVideoFormatDescriptionRef inputFormat = nullptr;
+ if (webrtc::H264AnnexBBufferHasVideoFormatDescription((uint8_t *)inputImage.buffer.bytes,
+ inputImage.buffer.length)) {
+ inputFormat = webrtc::CreateVideoFormatDescription((uint8_t *)inputImage.buffer.bytes,
+ inputImage.buffer.length);
+ if (inputFormat) {
// Check if the video format has changed, and reinitialize decoder if
// needed.
- if (!CMFormatDescriptionEqual(input_format, video_format_)) {
- SetVideoFormat(input_format);
- ResetDecompressionSession();
+ if (!CMFormatDescriptionEqual(inputFormat, _videoFormat)) {
+ [self setVideoFormat:inputFormat];
+ [self resetDecompressionSession];
}
- CFRelease(input_format);
+ CFRelease(inputFormat);
}
}
- if (!video_format_) {
+ if (!_videoFormat) {
// We received a frame but we don't have format information so we can't
// decode it.
// This can happen after backgrounding. We need to wait for the next
@@ -131,34 +118,29 @@ int H264VideoToolboxDecoder::Decode(
LOG(LS_WARNING) << "Missing video format. Frame with sps/pps required.";
return WEBRTC_VIDEO_CODEC_ERROR;
}
- CMSampleBufferRef sample_buffer = nullptr;
- if (!H264AnnexBBufferToCMSampleBuffer(input_image._buffer,
- input_image._length, video_format_,
- &sample_buffer)) {
+ CMSampleBufferRef sampleBuffer = nullptr;
+ if (!webrtc::H264AnnexBBufferToCMSampleBuffer((uint8_t *)inputImage.buffer.bytes,
+ inputImage.buffer.length,
+ _videoFormat,
+ &sampleBuffer)) {
return WEBRTC_VIDEO_CODEC_ERROR;
}
- RTC_DCHECK(sample_buffer);
- VTDecodeFrameFlags decode_flags =
- kVTDecodeFrame_EnableAsynchronousDecompression;
- std::unique_ptr<FrameDecodeParams> frame_decode_params;
- frame_decode_params.reset(
- new FrameDecodeParams(callback_, input_image._timeStamp));
+ RTC_DCHECK(sampleBuffer);
+ VTDecodeFrameFlags decodeFlags = kVTDecodeFrame_EnableAsynchronousDecompression;
+ std::unique_ptr<RTCFrameDecodeParams> frameDecodeParams;
+ frameDecodeParams.reset(new RTCFrameDecodeParams(_callback, inputImage.timeStamp));
OSStatus status = VTDecompressionSessionDecodeFrame(
- decompression_session_, sample_buffer, decode_flags,
- frame_decode_params.release(), nullptr);
+ _decompressionSession, sampleBuffer, decodeFlags, frameDecodeParams.release(), nullptr);
#if defined(WEBRTC_IOS)
// Re-initialize the decoder if we have an invalid session while the app is
// active and retry the decode request.
- if (status == kVTInvalidSessionErr &&
- ResetDecompressionSession() == WEBRTC_VIDEO_CODEC_OK) {
- frame_decode_params.reset(
- new FrameDecodeParams(callback_, input_image._timeStamp));
+ if (status == kVTInvalidSessionErr && [self resetDecompressionSession] == WEBRTC_VIDEO_CODEC_OK) {
+ frameDecodeParams.reset(new RTCFrameDecodeParams(_callback, inputImage.timeStamp));
status = VTDecompressionSessionDecodeFrame(
- decompression_session_, sample_buffer, decode_flags,
- frame_decode_params.release(), nullptr);
+ _decompressionSession, sampleBuffer, decodeFlags, frameDecodeParams.release(), nullptr);
}
#endif
- CFRelease(sample_buffer);
+ CFRelease(sampleBuffer);
if (status != noErr) {
LOG(LS_ERROR) << "Failed to decode frame with code: " << status;
return WEBRTC_VIDEO_CODEC_ERROR;
@@ -166,27 +148,26 @@ int H264VideoToolboxDecoder::Decode(
return WEBRTC_VIDEO_CODEC_OK;
}
-int H264VideoToolboxDecoder::RegisterDecodeCompleteCallback(
- DecodedImageCallback* callback) {
- RTC_DCHECK(!callback_);
- callback_ = callback;
- return WEBRTC_VIDEO_CODEC_OK;
+- (void)setCallback:(RTCVideoDecoderCallback)callback {
+ _callback = callback;
}
-int H264VideoToolboxDecoder::Release() {
+- (NSInteger)releaseDecoder {
// Need to invalidate the session so that callbacks no longer occur and it
// is safe to null out the callback.
- DestroyDecompressionSession();
- SetVideoFormat(nullptr);
- callback_ = nullptr;
+ [self destroyDecompressionSession];
+ [self setVideoFormat:nullptr];
+ _callback = nullptr;
return WEBRTC_VIDEO_CODEC_OK;
}
-int H264VideoToolboxDecoder::ResetDecompressionSession() {
- DestroyDecompressionSession();
+#pragma mark - Private
+
+- (int)resetDecompressionSession {
+ [self destroyDecompressionSession];
// Need to wait for the first SPS to initialize decoder.
- if (!video_format_) {
+ if (!_videoFormat) {
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -198,8 +179,8 @@ int H264VideoToolboxDecoder::ResetDecompressionSession() {
// CVPixelBuffers directly to the renderer.
// TODO(tkchin): Maybe only set OpenGL/IOSurface keys if we know that that
// we can pass CVPixelBuffers as native handles in decoder output.
- static size_t const attributes_size = 3;
- CFTypeRef keys[attributes_size] = {
+ static size_t const attributesSize = 3;
+ CFTypeRef keys[attributesSize] = {
#if defined(WEBRTC_IOS)
kCVPixelBufferOpenGLESCompatibilityKey,
#elif defined(WEBRTC_MAC)
@@ -208,70 +189,64 @@ int H264VideoToolboxDecoder::ResetDecompressionSession() {
kCVPixelBufferIOSurfacePropertiesKey,
kCVPixelBufferPixelFormatTypeKey
};
- CFDictionaryRef io_surface_value = CreateCFDictionary(nullptr, nullptr, 0);
+ CFDictionaryRef ioSurfaceValue = CreateCFTypeDictionary(nullptr, nullptr, 0);
int64_t nv12type = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange;
- CFNumberRef pixel_format =
- CFNumberCreate(nullptr, kCFNumberLongType, &nv12type);
- CFTypeRef values[attributes_size] = {kCFBooleanTrue, io_surface_value,
- pixel_format};
- CFDictionaryRef attributes =
- CreateCFDictionary(keys, values, attributes_size);
- if (io_surface_value) {
- CFRelease(io_surface_value);
- io_surface_value = nullptr;
+ CFNumberRef pixelFormat = CFNumberCreate(nullptr, kCFNumberLongType, &nv12type);
+ CFTypeRef values[attributesSize] = {kCFBooleanTrue, ioSurfaceValue, pixelFormat};
+ CFDictionaryRef attributes = CreateCFTypeDictionary(keys, values, attributesSize);
+ if (ioSurfaceValue) {
+ CFRelease(ioSurfaceValue);
+ ioSurfaceValue = nullptr;
}
- if (pixel_format) {
- CFRelease(pixel_format);
- pixel_format = nullptr;
+ if (pixelFormat) {
+ CFRelease(pixelFormat);
+ pixelFormat = nullptr;
}
VTDecompressionOutputCallbackRecord record = {
- VTDecompressionOutputCallback, this,
+ decompressionOutputCallback, nullptr,
};
- OSStatus status =
- VTDecompressionSessionCreate(nullptr, video_format_, nullptr, attributes,
- &record, &decompression_session_);
+ OSStatus status = VTDecompressionSessionCreate(
+ nullptr, _videoFormat, nullptr, attributes, &record, &_decompressionSession);
CFRelease(attributes);
if (status != noErr) {
- DestroyDecompressionSession();
+ [self destroyDecompressionSession];
return WEBRTC_VIDEO_CODEC_ERROR;
}
- ConfigureDecompressionSession();
+ [self configureDecompressionSession];
return WEBRTC_VIDEO_CODEC_OK;
}
-void H264VideoToolboxDecoder::ConfigureDecompressionSession() {
- RTC_DCHECK(decompression_session_);
+- (void)configureDecompressionSession {
+ RTC_DCHECK(_decompressionSession);
#if defined(WEBRTC_IOS)
- VTSessionSetProperty(decompression_session_,
- kVTDecompressionPropertyKey_RealTime, kCFBooleanTrue);
+ VTSessionSetProperty(_decompressionSession, kVTDecompressionPropertyKey_RealTime, kCFBooleanTrue);
#endif
}
-void H264VideoToolboxDecoder::DestroyDecompressionSession() {
- if (decompression_session_) {
- VTDecompressionSessionInvalidate(decompression_session_);
- CFRelease(decompression_session_);
- decompression_session_ = nullptr;
+- (void)destroyDecompressionSession {
+ if (_decompressionSession) {
+ VTDecompressionSessionInvalidate(_decompressionSession);
+ CFRelease(_decompressionSession);
+ _decompressionSession = nullptr;
}
}
-void H264VideoToolboxDecoder::SetVideoFormat(
- CMVideoFormatDescriptionRef video_format) {
- if (video_format_ == video_format) {
+- (void)setVideoFormat:(CMVideoFormatDescriptionRef)videoFormat {
+ if (_videoFormat == videoFormat) {
return;
}
- if (video_format_) {
- CFRelease(video_format_);
+ if (_videoFormat) {
+ CFRelease(_videoFormat);
}
- video_format_ = video_format;
- if (video_format_) {
- CFRetain(video_format_);
+ _videoFormat = videoFormat;
+ if (_videoFormat) {
+ CFRetain(_videoFormat);
}
}
-const char* H264VideoToolboxDecoder::ImplementationName() const {
- return "VideoToolbox";
+- (NSString *)implementationName {
+ return @"VideoToolbox";
}
-} // namespace webrtc
+@end

Powered by Google App Engine
This is Rietveld 408576698