diff --git a/VideoCore.podspec b/VideoCore.podspec index 2f47d3c7..4e1f501a 100644 --- a/VideoCore.podspec +++ b/VideoCore.podspec @@ -32,7 +32,7 @@ Pod::Spec.new do |s| s.libraries = 'c++' s.dependency 'boost', '~> 1.51.0' - s.dependency 'glm', '~> 0.9.4.6' + s.dependency 'glm', '~> 0.9' s.dependency 'UriParser-cpp', '~> 0.1.3' s.xcconfig = { "HEADER_SEARCH_PATHS" => "${PODS_ROOT}/boost" } diff --git a/api/iOS/VCPreviewView.mm b/api/iOS/VCPreviewView.mm index 55bcd545..2d6bf144 100644 --- a/api/iOS/VCPreviewView.mm +++ b/api/iOS/VCPreviewView.mm @@ -110,7 +110,7 @@ - (void) initInternal { [bSelf setupGLES]; }); [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notification:) name:UIApplicationDidEnterBackgroundNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notification:) name:UIApplicationWillEnterForegroundNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notification:) name:UIApplicationDidBecomeActiveNotification object:nil]; } - (void) dealloc { @@ -156,7 +156,7 @@ - (void) layoutSubviews - (void) notification: (NSNotification*) notification { if([notification.name isEqualToString:UIApplicationDidEnterBackgroundNotification]) { _paused = true; - } else if([notification.name isEqualToString:UIApplicationWillEnterForegroundNotification]) { + } else if([notification.name isEqualToString:UIApplicationDidBecomeActiveNotification]) { _paused = false; } } @@ -164,7 +164,6 @@ - (void) notification: (NSNotification*) notification { - (void) drawFrame:(CVPixelBufferRef)pixelBuffer { - if(_paused) return; bool updateTexture = false; diff --git a/api/iOS/VCSimpleSession.h b/api/iOS/VCSimpleSession.h index 7009aa46..fc5e98fd 100644 --- a/api/iOS/VCSimpleSession.h +++ b/api/iOS/VCSimpleSession.h @@ -50,7 +50,8 @@ typedef NS_ENUM(NSInteger, VCSessionState) typedef NS_ENUM(NSInteger, VCCameraState) { VCCameraStateFront, - VCCameraStateBack + VCCameraStateBack, + VCCameraStateCustom }; typedef NS_ENUM(NSInteger, VCAspectMode) @@ -66,9 +67,14 @@ typedef NS_ENUM(NSInteger, VCFilter) { VCFilterInvertColors, VCFilterSepia, VCFilterFisheye, - VCFilterGlow + VCFilterGlow, + VCFilterBeauty +}; +typedef NS_ENUM(NSInteger, VCDisconnectReason) { + VCDisconnectReasonManual, + VCDisconnectReasonDealloc, + VCDisconnectReasonConnectError }; - @protocol VCSessionDelegate @required - (void) connectionStatusChanged: (VCSessionState) sessionState; @@ -77,9 +83,12 @@ typedef NS_ENUM(NSInteger, VCFilter) { - (void) detectedThroughput: (NSInteger) throughputInBytesPerSecond; //Depreciated, should use method below - (void) detectedThroughput: (NSInteger) throughputInBytesPerSecond videoRate:(NSInteger) rate; +- (void) didDisconnectWithReason:(VCDisconnectReason)reason; @end -@interface VCSimpleSession : NSObject +@interface VCSimpleSession : NSObject { + +} @property (nonatomic, readonly) VCSessionState rtmpSessionState; @property (nonatomic, strong, readonly) UIView* previewView; @@ -88,6 +97,7 @@ typedef NS_ENUM(NSInteger, VCFilter) { @property (nonatomic, assign) CGSize videoSize; // Change will not take place until the next RTMP Session @property (nonatomic, assign) int bitrate; // Change will not take place until the next RTMP Session @property (nonatomic, assign) int fps; // Change will not take place until the next RTMP Session +@property (nonatomic, assign) int audioBitrate; @property (nonatomic, assign, readonly) BOOL useInterfaceOrientation; @property (nonatomic, assign) VCCameraState cameraState; @property (nonatomic, assign) BOOL orientationLocked; @@ -105,6 +115,8 @@ typedef NS_ENUM(NSInteger, VCFilter) { @property (nonatomic, assign) VCAspectMode aspectMode; @property (nonatomic, assign) VCFilter filter; /* Default is VCFilterNormal*/ +@property (nonatomic, assign) BOOL customCamera; +@property (nonatomic, assign) BOOL customPreview; @property (nonatomic, assign) id delegate; @@ -135,11 +147,18 @@ typedef NS_ENUM(NSInteger, VCFilter) { aspectMode:(VCAspectMode) aspectMode; // ----------------------------------------------------------------------------- - +- (instancetype) initWithVideoSize:(CGSize)videoSize + frameRate:(int)fps + bitrate:(int)bps + useInterfaceOrientation:(BOOL)useInterfaceOrientation + cameraState:(VCCameraState) cameraState + aspectMode:(VCAspectMode)aspectMode + sessionPreset:(NSString*)sessionPreset; - (void) startRtmpSessionWithURL:(NSString*) rtmpUrl andStreamKey:(NSString*) streamKey; -- (void) endRtmpSession; +//- (void) endRtmpSession; +- (void) manualEndRtmpSession; - (void) getCameraPreviewLayer: (AVCaptureVideoPreviewLayer**) previewLayer; @@ -152,5 +171,9 @@ typedef NS_ENUM(NSInteger, VCFilter) { - (void) addPixelBufferSource: (UIImage*) image withRect: (CGRect) rect; +-(void)addPixelBufferSource:(CVPixelBufferRef)bufferRef + realImageSize:(CGSize)size + andRect:(CGRect)rect; +- (void) bufferCaptured:(CVPixelBufferRef)pixelBufferRef; @end diff --git a/api/iOS/VCSimpleSession.mm b/api/iOS/VCSimpleSession.mm index 8339d000..475d5100 100644 --- a/api/iOS/VCSimpleSession.mm +++ b/api/iOS/VCSimpleSession.mm @@ -32,11 +32,12 @@ of this software and associated documentation files (the "Software"), to deal #include #include #include +#include #ifdef __APPLE__ # include # include -# include +# include # include # ifdef TARGET_OS_IPHONE # include @@ -58,7 +59,7 @@ of this software and associated documentation files (the "Software"), to deal #include -static const int kMinVideoBitrate = 32000; +static const int kMinVideoBitrate = 384000; namespace videocore { namespace simpleApi { @@ -147,6 +148,7 @@ @interface VCSimpleSession() VCFilter _filter; } @property (nonatomic, readwrite) VCSessionState rtmpSessionState; +@property (nonatomic, readwrite) NSString *sessionPreset; - (void) setupGraph; @@ -259,13 +261,21 @@ - (void) setCameraState:(VCCameraState)cameraState if(m_cameraSource) { m_cameraSource->toggleCamera(); } + if (!self.customCamera){ + if (self.cameraState == VCCameraStateFront) { + m_aspectTransform->setHReverse(true); + } + else { + m_aspectTransform->setHReverse(false); + } + } } } - (void) setRtmpSessionState:(VCSessionState)rtmpSessionState { _rtmpSessionState = rtmpSessionState; if (NSOperationQueue.currentQueue != NSOperationQueue.mainQueue) { - dispatch_async(dispatch_get_main_queue(), ^{ + dispatch_sync(dispatch_get_main_queue(), ^{//TODO async-->sync // trigger in main thread, avoid autolayout engine exception if(self.delegate) { [self.delegate connectionStatusChanged:rtmpSessionState]; @@ -463,7 +473,41 @@ - (instancetype) initWithVideoSize:(CGSize)videoSize return self; } +- (instancetype) initWithVideoSize:(CGSize)videoSize + frameRate:(int)fps + bitrate:(int)bps + useInterfaceOrientation:(BOOL)useInterfaceOrientation + cameraState:(VCCameraState) cameraState + aspectMode:(VCAspectMode)aspectMode + sessionPreset:(NSString*)sessionPreset +{ + if (( self = [super init] )) + { + [self initInternalWithVideoSize:videoSize + frameRate:fps + bitrate:bps + useInterfaceOrientation:useInterfaceOrientation + cameraState:cameraState + aspectMode:aspectMode + sessionPreset:sessionPreset]; + } + return self; +} +- (void) initInternalWithVideoSize:(CGSize)videoSize + frameRate:(int)fps + bitrate:(int)bps + useInterfaceOrientation:(BOOL)useInterfaceOrientation + cameraState:(VCCameraState) cameraState + aspectMode:(VCAspectMode)aspectMode{ + [self initInternalWithVideoSize:videoSize + frameRate:fps + bitrate:bps + useInterfaceOrientation:useInterfaceOrientation + cameraState:cameraState + aspectMode:aspectMode + sessionPreset:AVCaptureSessionPreset1280x720]; +} - (void) initInternalWithVideoSize:(CGSize)videoSize frameRate:(int)fps @@ -471,6 +515,7 @@ - (void) initInternalWithVideoSize:(CGSize)videoSize useInterfaceOrientation:(BOOL)useInterfaceOrientation cameraState:(VCCameraState) cameraState aspectMode:(VCAspectMode)aspectMode + sessionPreset:(NSString*)sessionPreset { self.bitrate = bps; self.videoSize = videoSize; @@ -481,16 +526,21 @@ - (void) initInternalWithVideoSize:(CGSize)videoSize self.audioSampleRate = 44100.; self.useAdaptiveBitrate = NO; self.aspectMode = aspectMode; + self.audioBitrate = 80000; _previewView = [[VCPreviewView alloc] init]; self.videoZoomFactor = 1.f; + self.customPreview = NO; _cameraState = cameraState; + self.customCamera = cameraState == VCCameraStateCustom; + _exposurePOI = _focusPOI = CGPointMake(0.5f, 0.5f); _continuousExposure = _continuousAutofocus = YES; _graphManagementQueue = dispatch_queue_create("com.videocore.session.graph", 0); - + + self.sessionPreset = sessionPreset; __block VCSimpleSession* bSelf = self; dispatch_async(_graphManagementQueue, ^{ @@ -501,6 +551,7 @@ - (void) initInternalWithVideoSize:(CGSize)videoSize - (void) dealloc { [self endRtmpSession]; + [self didDisconnectWithReason:VCDisconnectReasonDealloc]; m_audioMixer.reset(); m_videoMixer.reset(); m_videoSplit.reset(); @@ -531,7 +582,11 @@ - (void) startSessionInternal: (NSString*) rtmpUrl streamKey: (NSString*) streamKey { std::stringstream uri ; - uri << (rtmpUrl ? [rtmpUrl UTF8String] : "") << "/" << (streamKey ? [streamKey UTF8String] : ""); + if (streamKey) { + uri << (rtmpUrl ? [rtmpUrl UTF8String] : "") << "/" << ([streamKey UTF8String] ); + }else{ + uri << (rtmpUrl ? [rtmpUrl UTF8String] : ""); + } m_outputSession.reset( new videocore::RTMPSession ( uri.str(), @@ -559,10 +614,12 @@ - (void) startSessionInternal: (NSString*) rtmpUrl case kClientStateError: self.rtmpSessionState = VCSessionStateError; [self endRtmpSession]; + [self didDisconnectWithReason:VCDisconnectReasonConnectError]; break; case kClientStateNotConnected: self.rtmpSessionState = VCSessionStateEnded; [self endRtmpSession]; + [self didDisconnectWithReason:VCDisconnectReasonConnectError]; break; default: break; @@ -602,30 +659,7 @@ - (void) startSessionInternal: (NSString*) rtmpUrl videoBr = video->bitrate(); - if (audio) { - - if ( videoBr > 500000 ) { - audio->setBitrate(128000); - } else if (videoBr <= 500000 && videoBr > 250000) { - audio->setBitrate(96000); - } else { - audio->setBitrate(80000); - } - } - - - if(videoBr > 1152000) { - video->setBitrate(std::min(int((videoBr / 384000 + vector )) * 384000, bSelf->_bpsCeiling) ); - } - else if( videoBr > 512000 ) { - video->setBitrate(std::min(int((videoBr / 128000 + vector )) * 128000, bSelf->_bpsCeiling) ); - } - else if( videoBr > 128000 ) { - video->setBitrate(std::min(int((videoBr / 64000 + vector )) * 64000, bSelf->_bpsCeiling) ); - } - else { - video->setBitrate(std::max(std::min(int((videoBr / 32000 + vector )) * 32000, bSelf->_bpsCeiling), kMinVideoBitrate) ); - } + video->setBitrate(std::max(std::min(int((videoBr / 128000 + vector )) * 128000, bSelf->_bpsCeiling), kMinVideoBitrate)); DLog("\n(%f) AudioBR: %d VideoBR: %d (%f)\n", vector, audio->bitrate(), video->bitrate(), predicted); } /* if(vector != 0) */ @@ -645,6 +679,10 @@ - (void) startSessionInternal: (NSString*) rtmpUrl m_outputSession->setSessionParameters(sp); } +- (void) manualEndRtmpSession{ + [self endRtmpSession]; + [self didDisconnectWithReason:VCDisconnectReasonManual]; +} - (void) endRtmpSession { @@ -660,6 +698,20 @@ - (void) endRtmpSession self.rtmpSessionState = VCSessionStateEnded; } +- (void)didDisconnectWithReason:(VCDisconnectReason)reason{ + if (NSOperationQueue.currentQueue != NSOperationQueue.mainQueue) { + dispatch_sync(dispatch_get_main_queue(), ^{//TODO async-->sync + // trigger in main thread, avoid autolayout engine exception + if(self.delegate && [self.delegate respondsToSelector:@selector(didDisconnectWithReason:)]) { + [self.delegate didDisconnectWithReason:reason]; + } + }); + } else { + if (self.delegate && [self.delegate respondsToSelector:@selector(didDisconnectWithReason:)]) { + [self.delegate didDisconnectWithReason:reason]; + } + } +} - (void) getCameraPreviewLayer:(AVCaptureVideoPreviewLayer **)previewLayer { if(m_cameraSource) { m_cameraSource->getPreviewLayer((void**)previewLayer); @@ -689,6 +741,9 @@ - (void)setFilter:(VCFilter)filterToChange { case VCFilterGlow: filterName = @"com.videocore.filters.glow"; break; + case VCFilterBeauty: + filterName = @"com.videocore.filters.beauty"; + break; default: break; } @@ -742,7 +797,9 @@ - (void) setupGraph m_pbOutput = std::make_shared([=](const void* const data, size_t size){ CVPixelBufferRef ref = (CVPixelBufferRef)data; - [preview drawFrame:ref]; + if (!self.customPreview) { + [preview drawFrame:ref]; + } if(self.rtmpSessionState == VCSessionStateNone) { self.rtmpSessionState = VCSessionStatePreviewStarted; } @@ -764,31 +821,43 @@ - (void) setupGraph m_cameraSource = std::make_shared(); m_cameraSource->setOrientationLocked(self.orientationLocked); auto aspectTransform = std::make_shared(self.videoSize.width,self.videoSize.height,m_aspectMode); + if (!self.customCamera && + self.cameraState == VCCameraStateFront) { + aspectTransform->setHReverse(YES); + } auto positionTransform = std::make_shared(self.videoSize.width/2, self.videoSize.height/2, self.videoSize.width * self.videoZoomFactor, self.videoSize.height * self.videoZoomFactor, self.videoSize.width, self.videoSize.height ); - - std::dynamic_pointer_cast(m_cameraSource)->setupCamera(self.fps,(self.cameraState == VCCameraStateFront),self.useInterfaceOrientation,nil,^{ + void (^setupCameraCallback)() = ^(){ m_cameraSource->setContinuousAutofocus(true); m_cameraSource->setContinuousExposure(true); - + m_cameraSource->setOutput(aspectTransform); - + m_videoMixer->setSourceFilter(m_cameraSource, dynamic_cast(m_videoMixer->filterFactory().filter("com.videocore.filters.bgra"))); _filter = VCFilterNormal; + + videocore::filters::BeautyVideoFilter * filter = (videocore::filters::BeautyVideoFilter*)m_videoMixer->filterFactory().filter("com.videocore.filters.beauty"); + filter->setOutputSize(self.videoSize.width, self.videoSize.height); + aspectTransform->setOutput(positionTransform); positionTransform->setOutput(m_videoMixer); m_aspectTransform = aspectTransform; m_positionTransform = positionTransform; - + // Inform delegate that camera source has been added if ([_delegate respondsToSelector:@selector(didAddCameraSource:)]) { [_delegate didAddCameraSource:self]; } - }); + }; + if (self.cameraState == VCCameraStateCustom) { + setupCameraCallback(); + }else{ + std::dynamic_pointer_cast(m_cameraSource)->setupCamera(self.fps,(self.cameraState == VCCameraStateFront),self.useInterfaceOrientation,self.sessionPreset,setupCameraCallback); + } } { // Add mic source @@ -811,10 +880,10 @@ - (void) addEncodersAndPacketizers { // Add encoders - m_aacEncoder = std::make_shared(self.audioSampleRate, self.audioChannelCount, 96000); + m_aacEncoder = std::make_shared(self.audioSampleRate, self.audioChannelCount, self.audioBitrate); if(SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0")) { // If >= iOS 8.0 use the VideoToolbox encoder that does not write to disk. - m_h264Encoder = std::make_shared(self.videoSize.width, + m_h264Encoder = std::make_shared(self.videoSize.width, self.videoSize.height, self.fps, self.bitrate, @@ -899,6 +968,44 @@ - (void) addPixelBufferSource: (UIImage*) image free(rawData); } +-(void)addPixelBufferSource:(CVPixelBufferRef)bufferRef + realImageSize:(CGSize)size + andRect:(CGRect)rect{ + + NSInteger width = size.width; + NSInteger height = size.height; + + CVPixelBufferLockBaseAddress(bufferRef, 0); + GLubyte *rawImageBytes = (GLubyte *)CVPixelBufferGetBaseAddress(bufferRef); //CASTED I DONT kNOW WHY + size_t dataSize = CVPixelBufferGetDataSize(bufferRef); + unsigned char* buffer = (unsigned char*)malloc( dataSize ); + memcpy(buffer, rawImageBytes, dataSize); + CVPixelBufferUnlockBaseAddress(bufferRef, 0); + + if(m_pixelBufferSource){ + m_pixelBufferSource->pushPixelBuffer(buffer, width * height * 4); + }else{ + m_pixelBufferSource = std::make_shared(width, height, kCVPixelFormatType_32BGRA); + + m_pbAspect = std::make_shared(self.videoSize.width,self.videoSize.height,m_aspectMode); + + m_pbPosition = std::make_shared(self.videoSize.width/2, self.videoSize.height/2, + self.videoSize.width * self.videoZoomFactor, self.videoSize.height * self.videoZoomFactor, + self.videoSize.width, self.videoSize.height + ); + NSLog(@"rect:%@\nvideoSize:%@",[NSValue valueWithCGRect:rect],[NSValue valueWithCGSize:self.videoSize]); + m_pixelBufferSource->setOutput(m_pbAspect); + m_pbAspect->setOutput(m_pbPosition); + m_pbPosition->setOutput(m_videoMixer); + m_videoMixer->registerSource(m_pixelBufferSource); + m_pixelBufferSource->pushPixelBuffer(buffer, width * height * 4); + } + free(buffer); + +} +- (void) bufferCaptured:(CVPixelBufferRef)pixelBufferRef{ + self->m_cameraSource->bufferCaptured(pixelBufferRef); +} - (NSString *) applicationDocumentsDirectory { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); diff --git a/filters/Basic/BasicVideoFilterBGRAinYUVAout.cpp b/filters/Basic/BasicVideoFilterBGRAinYUVAout.cpp index 8b4b4e0c..478d6c89 100644 --- a/filters/Basic/BasicVideoFilterBGRAinYUVAout.cpp +++ b/filters/Basic/BasicVideoFilterBGRAinYUVAout.cpp @@ -17,7 +17,7 @@ namespace videocore { namespace filters { bool BasicVideoFilterBGRAinYUVAout::registerFilter() { - FilterFactory::_register("com.videocore.filters.bgra2yuva", []() { return new BasicVideoFilterBGRAinYUVAout(); }); + FilterFactory::_register("com.videocore.filters.bgra2yuva", []() { return new BasicVideoFilterBGRAinYUVAout(); });//TODO 尝试在kCVPixelBufferPixelFormatTypeKey = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange 时使用这个filter,看能否正常解析出画面 return true; } diff --git a/filters/Basic/BeautyVideoFilter.cpp b/filters/Basic/BeautyVideoFilter.cpp new file mode 100644 index 00000000..5a30c0de --- /dev/null +++ b/filters/Basic/BeautyVideoFilter.cpp @@ -0,0 +1,259 @@ +// +// BeautyVideoFilter.cpp +// Pods +// +// Created by wheelswang on 16/2/1. +// +// + +#include + +#include + + +#ifdef TARGET_OS_IPHONE + +#include +#include +#include +#include + +#endif + +namespace videocore { namespace filters { + + bool BeautyVideoFilter::s_registered = BeautyVideoFilter::registerFilter(); + + bool + BeautyVideoFilter::registerFilter() + { + FilterFactory::_register("com.videocore.filters.beauty", []() { return new BeautyVideoFilter(); }); + return true; + } + + BeautyVideoFilter::BeautyVideoFilter() + : IVideoFilter(), m_initialized(false), m_bound(false) + { + + } + BeautyVideoFilter::~BeautyVideoFilter() + { + glDeleteProgram(m_program); + glDeleteVertexArraysOES(1, &m_vao); + } + + const char * const + BeautyVideoFilter::vertexKernel() const + { + KERNEL(GL_ES2_3, m_language, + attribute vec4 position; + attribute vec4 inputTextureCoordinate; + varying vec2 textureCoordinate; + uniform mat4 uMat; + + void main() + { + gl_Position = uMat * position; + textureCoordinate = inputTextureCoordinate.xy; + } + ) + + return nullptr; + } + + const char * const + BeautyVideoFilter::pixelKernel() const + { + + KERNEL(GL_ES2_3, m_language, + precision highp float; + + uniform sampler2D inputImageTexture; + uniform vec2 singleStepOffset; + uniform highp vec4 params; + + varying highp vec2 textureCoordinate; + + const highp vec3 W = vec3(0.299,0.587,0.114); + const mat3 saturateMatrix = mat3( + 1.1102,-0.0598,-0.061, + -0.0774,1.0826,-0.1186, + -0.0228,-0.0228,1.1772); + float hardlight(float color) + { + if(color <= 0.5) + { + color = color * color * 2.0; + } + else + { + color = 1.0 - ((1.0 - color)*(1.0 - color) * 2.0); + } + return color; + } + + void main(){ + vec2 blurCoordinates[24]; + + blurCoordinates[0] = textureCoordinate.xy + singleStepOffset * vec2(0.0, -10.0); + blurCoordinates[1] = textureCoordinate.xy + singleStepOffset * vec2(0.0, 10.0); + blurCoordinates[2] = textureCoordinate.xy + singleStepOffset * vec2(-10.0, 0.0); + blurCoordinates[3] = textureCoordinate.xy + singleStepOffset * vec2(10.0, 0.0); + + blurCoordinates[4] = textureCoordinate.xy + singleStepOffset * vec2(5.0, -8.0); + blurCoordinates[5] = textureCoordinate.xy + singleStepOffset * vec2(5.0, 8.0); + blurCoordinates[6] = textureCoordinate.xy + singleStepOffset * vec2(-5.0, 8.0); + blurCoordinates[7] = textureCoordinate.xy + singleStepOffset * vec2(-5.0, -8.0); + + blurCoordinates[8] = textureCoordinate.xy + singleStepOffset * vec2(8.0, -5.0); + blurCoordinates[9] = textureCoordinate.xy + singleStepOffset * vec2(8.0, 5.0); + blurCoordinates[10] = textureCoordinate.xy + singleStepOffset * vec2(-8.0, 5.0); + blurCoordinates[11] = textureCoordinate.xy + singleStepOffset * vec2(-8.0, -5.0); + + blurCoordinates[12] = textureCoordinate.xy + singleStepOffset * vec2(0.0, -6.0); + blurCoordinates[13] = textureCoordinate.xy + singleStepOffset * vec2(0.0, 6.0); + blurCoordinates[14] = textureCoordinate.xy + singleStepOffset * vec2(6.0, 0.0); + blurCoordinates[15] = textureCoordinate.xy + singleStepOffset * vec2(-6.0, 0.0); + + blurCoordinates[16] = textureCoordinate.xy + singleStepOffset * vec2(-4.0, -4.0); + blurCoordinates[17] = textureCoordinate.xy + singleStepOffset * vec2(-4.0, 4.0); + blurCoordinates[18] = textureCoordinate.xy + singleStepOffset * vec2(4.0, -4.0); + blurCoordinates[19] = textureCoordinate.xy + singleStepOffset * vec2(4.0, 4.0); + + blurCoordinates[20] = textureCoordinate.xy + singleStepOffset * vec2(-2.0, -2.0); + blurCoordinates[21] = textureCoordinate.xy + singleStepOffset * vec2(-2.0, 2.0); + blurCoordinates[22] = textureCoordinate.xy + singleStepOffset * vec2(2.0, -2.0); + blurCoordinates[23] = textureCoordinate.xy + singleStepOffset * vec2(2.0, 2.0); + + + float sampleColor = texture2D(inputImageTexture, textureCoordinate).g * 22.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[0]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[1]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[2]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[3]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[4]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[5]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[6]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[7]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[8]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[9]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[10]).g; + sampleColor += texture2D(inputImageTexture, blurCoordinates[11]).g; + + sampleColor += texture2D(inputImageTexture, blurCoordinates[12]).g * 2.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[13]).g * 2.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[14]).g * 2.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[15]).g * 2.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[16]).g * 2.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[17]).g * 2.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[18]).g * 2.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[19]).g * 2.0; + + sampleColor += texture2D(inputImageTexture, blurCoordinates[20]).g * 3.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[21]).g * 3.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[22]).g * 3.0; + sampleColor += texture2D(inputImageTexture, blurCoordinates[23]).g * 3.0; + + sampleColor = sampleColor / 62.0; + + vec3 centralColor = texture2D(inputImageTexture, textureCoordinate).rgb; + + float highpass = centralColor.g - sampleColor + 0.5; + + for(int i = 0; i < 5;i++) + { + highpass = hardlight(highpass); + } + float lumance = dot(centralColor, W); + + float alpha = pow(lumance, params.r); + + vec3 smoothColor = centralColor + (centralColor-vec3(highpass))*alpha*0.1; + + smoothColor.r = clamp(pow(smoothColor.r, params.g),0.0,1.0); + smoothColor.g = clamp(pow(smoothColor.g, params.g),0.0,1.0); + smoothColor.b = clamp(pow(smoothColor.b, params.g),0.0,1.0); + + vec3 lvse = vec3(1.0)-(vec3(1.0)-smoothColor)*(vec3(1.0)-centralColor); + vec3 bianliang = max(smoothColor, centralColor); + vec3 rouguang = 2.0*centralColor*smoothColor + centralColor*centralColor - 2.0*centralColor*centralColor*smoothColor; + + gl_FragColor = vec4(mix(centralColor, lvse, alpha), 1.0); + gl_FragColor.rgb = mix(gl_FragColor.rgb, bianliang, alpha); + gl_FragColor.rgb = mix(gl_FragColor.rgb, rouguang, params.b); + + vec3 satcolor = gl_FragColor.rgb * saturateMatrix; + gl_FragColor.rgb = mix(gl_FragColor.rgb, satcolor, params.a); + } + ) + + return nullptr; + } + void + BeautyVideoFilter::initialize() + { + switch(m_language) { + case GL_ES2_3: + case GL_2: { + setProgram(build_program(vertexKernel(), pixelKernel())); + glGenVertexArraysOES(1, &m_vao); + glBindVertexArrayOES(m_vao); + int attrpos = glGetAttribLocation(m_program, "position"); + glEnableVertexAttribArray(attrpos); + glVertexAttribPointer(attrpos, BUFFER_SIZE_POSITION, GL_FLOAT, GL_FALSE, BUFFER_STRIDE, BUFFER_OFFSET_POSITION); + + int attrtex = glGetAttribLocation(m_program, "inputTextureCoordinate"); + glEnableVertexAttribArray(attrtex); + glVertexAttribPointer(attrtex, BUFFER_SIZE_POSITION, GL_FLOAT, GL_FALSE, BUFFER_STRIDE, BUFFER_OFFSET_TEXTURE); + + int unitex = glGetUniformLocation(m_program, "inputImageTexture"); + glUniform1i(unitex, 0); + + m_singleStepOffset = glGetUniformLocation(m_program, "singleStepOffset"); + m_params = glGetUniformLocation(m_program, "params"); + m_uMatrix = glGetUniformLocation(m_program, "uMat"); + + m_initialized = true; + } + break; + case GL_3: + break; + } + } + void + BeautyVideoFilter::bind() + { + switch(m_language) { + case GL_ES2_3: + case GL_2: + if(!m_bound) { + if(!initialized()) { + initialize(); + } + glUseProgram(m_program); + glBindVertexArrayOES(m_vao); + } + + glUniform2f(m_singleStepOffset, 2.0f/(int)m_width, 2.0f/(int)m_height); + glUniform4f(m_params, 0.4f, 0.7f, 0.38f, 0.30f); + glUniformMatrix4fv(m_uMatrix, 1, GL_FALSE, &m_matrix[0][0]); + + break; + case GL_3: + break; + } + } + void + BeautyVideoFilter::unbind() + { + m_bound = false; + } + + void + BeautyVideoFilter::setOutputSize(int width, int height) + { + m_width = width; + m_height = height; + } +} +} diff --git a/filters/Basic/BeautyVideoFilter.h b/filters/Basic/BeautyVideoFilter.h new file mode 100644 index 00000000..b5f588ff --- /dev/null +++ b/filters/Basic/BeautyVideoFilter.h @@ -0,0 +1,52 @@ +// +// MopiVideoFilter.hpp +// Pods +// +// Created by wheelswang on 16/2/1. +// +// + +#ifndef BeautyVideoFilter_h +#define BeautyVideoFilter_h +#include + +namespace videocore { + namespace filters { + class BeautyVideoFilter : public IVideoFilter { + + public: + BeautyVideoFilter(); + ~BeautyVideoFilter(); + + public: + virtual void initialize(); + virtual bool initialized() const { return m_initialized; }; + virtual std::string const name() { return "com.videocore.filters.beauty"; }; + virtual void bind(); + virtual void unbind(); + void setOutputSize(int width, int height); + + public: + + const char * const vertexKernel() const ; + const char * const pixelKernel() const ; + + private: + static bool registerFilter(); + static bool s_registered; + private: + + unsigned int m_uMatrix; + unsigned int m_vao; + unsigned int m_singleStepOffset; + unsigned int m_params; + bool m_initialized; + bool m_bound; + int m_width; + int m_height; + + }; + } +} + +#endif /* MopiVideoFilter_hpp */ diff --git a/filters/Basic/InvertColorsVideoFilter.cpp b/filters/Basic/InvertColorsVideoFilter.cpp index 8e47d17f..1d34e0d6 100644 --- a/filters/Basic/InvertColorsVideoFilter.cpp +++ b/filters/Basic/InvertColorsVideoFilter.cpp @@ -64,7 +64,7 @@ namespace videocore { namespace filters { void main(void) { vec4 color = texture2D(uTex0, vCoord); gl_FragColor = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b, color.a); - } + }//TODO 对比InvertColors 和 BGRA,把这个filter改成不反转颜色,尽量原样输出来模拟不加任何filter的情形 ) return nullptr; diff --git a/filters/FilterFactory.cpp b/filters/FilterFactory.cpp index 13b8722d..1fa5e323 100644 --- a/filters/FilterFactory.cpp +++ b/filters/FilterFactory.cpp @@ -5,6 +5,7 @@ #include #include #include +#include namespace videocore { std::map* FilterFactory::s_registration = nullptr ; @@ -17,6 +18,7 @@ namespace videocore { filters::SepiaVideoFilter s; filters::FisheyeVideoFilter f; filters::GlowVideoFilter gl; + filters::BeautyVideoFilter m; } } IFilter* diff --git a/sample/SampleBroadcaster-Swift/SampleBroadcaster-Swift/ViewController.swift b/sample/SampleBroadcaster-Swift/SampleBroadcaster-Swift/ViewController.swift index 481b93c6..3e2b8672 100644 --- a/sample/SampleBroadcaster-Swift/SampleBroadcaster-Swift/ViewController.swift +++ b/sample/SampleBroadcaster-Swift/SampleBroadcaster-Swift/ViewController.swift @@ -67,7 +67,7 @@ class ViewController: UIViewController, VCSessionDelegate case .None, .PreviewStarted, .Ended, .Error: session.startRtmpSessionWithURL("rtmp://192.168.1.151/live", andStreamKey: "myStream") default: - session.endRtmpSession() + session.manualEndRtmpSession() break } } diff --git a/sample/SampleBroadcaster/SampleBroadcaster.xcodeproj/project.pbxproj b/sample/SampleBroadcaster/SampleBroadcaster.xcodeproj/project.pbxproj index 95e0a8c6..b28049cf 100644 --- a/sample/SampleBroadcaster/SampleBroadcaster.xcodeproj/project.pbxproj +++ b/sample/SampleBroadcaster/SampleBroadcaster.xcodeproj/project.pbxproj @@ -181,7 +181,7 @@ ORGANIZATIONNAME = videocore; TargetAttributes = { 7265D5DB191994B80042DC3B = { - DevelopmentTeam = 263A46GSYZ; + DevelopmentTeam = 82CKJMD983; }; }; }; @@ -415,7 +415,7 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "videocore.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "802ea4ec-e810-451f-9144-bc91bd34dd7b"; + PROVISIONING_PROFILE = "2917814f-aa40-4a19-9f1a-789be782bb7d"; TARGETED_DEVICE_FAMILY = 1; WRAPPER_EXTENSION = app; }; @@ -469,7 +469,7 @@ LIBRARY_SEARCH_PATHS = "$(inherited)"; PRODUCT_BUNDLE_IDENTIFIER = "videocore.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE = "802ea4ec-e810-451f-9144-bc91bd34dd7b"; + PROVISIONING_PROFILE = "2917814f-aa40-4a19-9f1a-789be782bb7d"; TARGETED_DEVICE_FAMILY = 1; WRAPPER_EXTENSION = app; }; diff --git a/sample/SampleBroadcaster/SampleBroadcaster/ViewController.mm b/sample/SampleBroadcaster/SampleBroadcaster/ViewController.mm index 1e3321c0..8bba758d 100644 --- a/sample/SampleBroadcaster/SampleBroadcaster/ViewController.mm +++ b/sample/SampleBroadcaster/SampleBroadcaster/ViewController.mm @@ -75,7 +75,7 @@ - (IBAction)btnConnectTouch:(id)sender { [_session startRtmpSessionWithURL:@"rtmp://192.168.50.19/myapp" andStreamKey:@"iosstream?abc=xxx"]; break; default: - [_session endRtmpSession]; + [_session manualEndRtmpSession]; break; } } @@ -93,15 +93,15 @@ - (IBAction)btnFilterTouch:(id)sender { case VCFilterInvertColors: [_session setFilter:VCFilterSepia]; break; - case VCFilterSepia: - [_session setFilter:VCFilterFisheye]; - break; - case VCFilterFisheye: - [_session setFilter:VCFilterGlow]; - break; - case VCFilterGlow: - [_session setFilter:VCFilterNormal]; - break; +// case VCFilterSepia: +// [_session setFilter:VCFilterFisheye]; +// break; +// case VCFilterFisheye: +// [_session setFilter:VCFilterGlow]; +// break; +// case VCFilterGlow: +// [_session setFilter:VCFilterNormal]; +// break; default: break; } diff --git a/sources/iOS/CameraSource.h b/sources/iOS/CameraSource.h index bc2adacf..9d159a97 100644 --- a/sources/iOS/CameraSource.h +++ b/sources/iOS/CameraSource.h @@ -51,13 +51,13 @@ namespace videocore { namespace iOS { /*! ISource::setOutput */ void setOutput(std::shared_ptr output); - /*! + /*! * Get the AVCaptureVideoPreviewLayer associated with the camera output. * * \param outAVCaputreVideoPreviewLayer a pointer to an AVCaptureVideoPreviewLayer pointer. */ void getPreviewLayer(void** outAVCaptureVideoPreviewLayer); - + /*! * Setup camera properties * @@ -68,13 +68,13 @@ namespace videocore { namespace iOS { * \param callbackBlock block to be called after everything is set */ void setupCamera(int fps = 15, bool useFront = true, bool useInterfaceOrientation = false, NSString* sessionPreset = nil, void (^callbackBlock)(void) = nil); - + /*! * Toggle the camera between front and back-facing cameras. */ void toggleCamera(); - + /*! * If the orientation is locked, we ignore device / interface * orientation changes. @@ -95,7 +95,7 @@ namespace videocore { namespace iOS { * Attempt to turn the torch mode on or off. * * \param torchOn Bool indicating whether the torch should be on or off. - * + * * \return the actual state of the torch. */ bool setTorch(bool torchOn); @@ -124,11 +124,11 @@ namespace videocore { namespace iOS { private: - /*! + /*! * Get a camera with a specified position * * \param position The position to search for. - * + * * \return the camera device, if found. */ void* cameraWithPosition(int position); @@ -149,9 +149,9 @@ namespace videocore { namespace iOS { bool m_torchOn; bool m_useInterfaceOrientation; bool m_orientationLocked; - + }; } } -#endif /* defined(__videocore__CameraSource__) */ +#endif /* defined(__videocore__CameraSource__) */ \ No newline at end of file diff --git a/sources/iOS/CameraSource.mm b/sources/iOS/CameraSource.mm index ad2d6050..c4b7697d 100644 --- a/sources/iOS/CameraSource.mm +++ b/sources/iOS/CameraSource.mm @@ -72,7 +72,7 @@ - (void) orientationChanged: (NSNotification*) notification @end namespace videocore { namespace iOS { - + CameraSource::CameraSource() : @@ -135,7 +135,11 @@ - (void) orientationChanged: (NSNotification*) notification AVCaptureDeviceInput* input; AVCaptureVideoDataOutput* output; if(sessionPreset) { - session.sessionPreset = (NSString*)sessionPreset; + if ([session canSetSessionPreset:sessionPreset]) { + session.sessionPreset = (NSString*)sessionPreset; + }else{ + session.sessionPreset = AVCaptureSessionPresetLow; + } } bThis->m_captureSession = session; @@ -207,7 +211,7 @@ - (void) orientationChanged: (NSNotification*) notification } } - + void CameraSource::getPreviewLayer(void** outAVCaptureVideoPreviewLayer) { @@ -273,7 +277,7 @@ - (void) orientationChanged: (NSNotification*) notification } else { NSLog(@"Torch not available in current camera input"); } - + } [session commitConfiguration]; @@ -348,28 +352,28 @@ - (void) orientationChanged: (NSNotification*) notification case UIInterfaceOrientationPortraitUpsideDown: if(av.videoOrientation != AVCaptureVideoOrientationPortraitUpsideDown) { av.videoOrientation = AVCaptureVideoOrientationPortraitUpsideDown; - // reorient = true; + // reorient = true; } break; // UIInterfaceOrientationLandscapeRight, UIDeviceOrientationLandscapeLeft case UIInterfaceOrientationLandscapeRight: if(av.videoOrientation != AVCaptureVideoOrientationLandscapeRight) { av.videoOrientation = AVCaptureVideoOrientationLandscapeRight; - // reorient = true; + // reorient = true; } break; // UIInterfaceOrientationLandscapeLeft, UIDeviceOrientationLandscapeRight case UIInterfaceOrientationLandscapeLeft: if(av.videoOrientation != AVCaptureVideoOrientationLandscapeLeft) { av.videoOrientation = AVCaptureVideoOrientationLandscapeLeft; - // reorient = true; + // reorient = true; } break; // UIInterfaceOrientationPortrait, UIDeviceOrientationPortrait case UIInterfaceOrientationPortrait: if(av.videoOrientation != AVCaptureVideoOrientationPortrait) { av.videoOrientation = AVCaptureVideoOrientationPortrait; - // reorient = true; + // reorient = true; } break; default: @@ -377,7 +381,7 @@ - (void) orientationChanged: (NSNotification*) notification } } } - + //[session commitConfiguration]; if(m_torchOn) { setTorch(m_torchOn); @@ -415,7 +419,7 @@ - (void) orientationChanged: (NSNotification*) notification AVCaptureDevice* device = (AVCaptureDevice*)m_captureDevice; AVCaptureFocusMode newMode = wantsContinuous ? AVCaptureFocusModeContinuousAutoFocus : AVCaptureFocusModeAutoFocus; bool ret = [device isFocusModeSupported:newMode]; - + if(ret) { NSError *err = nil; if ([device lockForConfiguration:&err]) { @@ -428,16 +432,16 @@ - (void) orientationChanged: (NSNotification*) notification } else { NSLog(@"Focus mode not supported: %@", wantsContinuous ? @"AVCaptureFocusModeContinuousAutoFocus" : @"AVCaptureFocusModeAutoFocus"); } - + return ret; } - + bool CameraSource::setContinuousExposure(bool wantsContinuous) { AVCaptureDevice *device = (AVCaptureDevice *) m_captureDevice; AVCaptureExposureMode newMode = wantsContinuous ? AVCaptureExposureModeContinuousAutoExposure : AVCaptureExposureModeAutoExpose; bool ret = [device isExposureModeSupported:newMode]; - + if(ret) { NSError *err = nil; if ([device lockForConfiguration:&err]) { @@ -450,7 +454,7 @@ - (void) orientationChanged: (NSNotification*) notification } else { NSLog(@"Exposure mode not supported: %@", wantsContinuous ? @"AVCaptureExposureModeContinuousAutoExposure" : @"AVCaptureExposureModeAutoExpose"); } - + return ret; } diff --git a/stream/Apple/StreamSession.mm b/stream/Apple/StreamSession.mm index c1e32a75..a073b1fd 100644 --- a/stream/Apple/StreamSession.mm +++ b/stream/Apple/StreamSession.mm @@ -205,12 +205,12 @@ - (void) stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode } if(event & NSStreamEventErrorOccurred) { setStatus(kStreamStatusErrorEncountered, true); - if (NSIS(m_inputStream).streamError) { - NSLog(@"Input stream error:%@", NSIS(m_inputStream).streamError); - } - if (NSOS(m_outputStream).streamError) { - NSLog(@"Output stream error:%@", NSIS(m_outputStream).streamError); - } +// if (NSIS(m_inputStream).streamError) { +// NSLog(@"Input stream error:%@", NSIS(m_inputStream).streamError); +// } +// if (NSOS(m_outputStream).streamError) { +// NSLog(@"Output stream error:%@", NSIS(m_outputStream).streamError); +// } } } diff --git a/transforms/Apple/H264Encode.h b/transforms/Apple/H264EncodeApple.h similarity index 92% rename from transforms/Apple/H264Encode.h rename to transforms/Apple/H264EncodeApple.h index 2aef3ee4..022d55fd 100644 --- a/transforms/Apple/H264Encode.h +++ b/transforms/Apple/H264EncodeApple.h @@ -27,11 +27,11 @@ namespace videocore { namespace Apple { - class H264Encode : public IEncoder + class H264EncodeApple : public IEncoder { public: - H264Encode( int frame_w, int frame_h, int fps, int bitrate, bool useBaseline = true, int ctsOffset = 0 ); - ~H264Encode(); + H264EncodeApple( int frame_w, int frame_h, int fps, int bitrate, bool useBaseline = true, int ctsOffset = 0 ); + ~H264EncodeApple(); CVPixelBufferPoolRef pixelBufferPool(); diff --git a/transforms/Apple/H264Encode.mm b/transforms/Apple/H264EncodeApple.mm similarity index 92% rename from transforms/Apple/H264Encode.mm rename to transforms/Apple/H264EncodeApple.mm index 2c677f80..540ffe53 100644 --- a/transforms/Apple/H264Encode.mm +++ b/transforms/Apple/H264EncodeApple.mm @@ -34,7 +34,7 @@ #endif #include -#include +#include #include #if VERSION_OK==1 @@ -88,29 +88,29 @@ void vtCallback(void *outputCallbackRefCon, ppsSize += 4; memcpy(&pps_buf[0], &ppsSize, 4); - ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)sps_buf.get(),spsSize, pts.value, dts.value); - ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)pps_buf.get(),ppsSize, pts.value, dts.value); + ((H264EncodeApple*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)sps_buf.get(),spsSize, pts.value, dts.value); + ((H264EncodeApple*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)pps_buf.get(),ppsSize, pts.value, dts.value); } char* bufferData; size_t size; CMBlockBufferGetDataPointer(block, 0, NULL, &size, &bufferData); - ((H264Encode*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)bufferData,size, pts.value, dts.value); + ((H264EncodeApple*)outputCallbackRefCon)->compressionSessionOutput((uint8_t*)bufferData,size, pts.value, dts.value); } #endif - H264Encode::H264Encode( int frame_w, int frame_h, int fps, int bitrate, bool useBaseline, int ctsOffset) + H264EncodeApple::H264EncodeApple( int frame_w, int frame_h, int fps, int bitrate, bool useBaseline, int ctsOffset) : m_frameW(frame_w), m_frameH(frame_h), m_fps(fps), m_bitrate(bitrate), m_forceKeyframe(false), m_ctsOffset(ctsOffset) { setupCompressionSession( useBaseline ); } - H264Encode::~H264Encode() + H264EncodeApple::~H264EncodeApple() { teardownCompressionSession(); } void - H264Encode::pushBuffer(const uint8_t *const data, size_t size, videocore::IMetadata &metadata) + H264EncodeApple::pushBuffer(const uint8_t *const data, size_t size, videocore::IMetadata &metadata) { #if VERSION_OK if(m_compressionSession) { @@ -145,7 +145,7 @@ void vtCallback(void *outputCallbackRefCon, #endif } void - H264Encode::setupCompressionSession( bool useBaseline ) + H264EncodeApple::setupCompressionSession( bool useBaseline ) { m_baseline = useBaseline; @@ -264,7 +264,7 @@ void vtCallback(void *outputCallbackRefCon, } void - H264Encode::teardownCompressionSession() + H264EncodeApple::teardownCompressionSession() { #if VERSION_OK if(m_compressionSession) { @@ -274,7 +274,7 @@ void vtCallback(void *outputCallbackRefCon, #endif } void - H264Encode::compressionSessionOutput(const uint8_t *data, size_t size, uint64_t pts, uint64_t dts) + H264EncodeApple::compressionSessionOutput(const uint8_t *data, size_t size, uint64_t pts, uint64_t dts) { #if VERSION_OK auto l = m_output.lock(); @@ -286,12 +286,12 @@ void vtCallback(void *outputCallbackRefCon, } void - H264Encode::requestKeyframe() + H264EncodeApple::requestKeyframe() { m_forceKeyframe = true; } void - H264Encode::setBitrate(int bitrate) + H264EncodeApple::setBitrate(int bitrate) { #if VERSION_OK if(bitrate == m_bitrate) { @@ -310,7 +310,7 @@ void vtCallback(void *outputCallbackRefCon, OSStatus ret = VTSessionSetProperty((VTCompressionSessionRef)m_compressionSession, kVTCompressionPropertyKey_AverageBitRate, ref); if(ret != noErr) { - DLog("H264Encode::setBitrate Error setting bitrate! %d", (int) ret); + DLog("H264EncodeApple::setBitrate Error setting bitrate! %d", (int) ret); } CFRelease(ref); ret = VTSessionCopyProperty((VTCompressionSessionRef)m_compressionSession, kVTCompressionPropertyKey_AverageBitRate, kCFAllocatorDefault, &ref); @@ -347,7 +347,7 @@ void vtCallback(void *outputCallbackRefCon, } CVPixelBufferPoolRef - H264Encode::pixelBufferPool() { + H264EncodeApple::pixelBufferPool() { if(m_compressionSession) { return VTCompressionSessionGetPixelBufferPool((VTCompressionSessionRef)m_compressionSession); } diff --git a/transforms/AspectTransform.cpp b/transforms/AspectTransform.cpp index 04ffbf9a..ea625ba7 100644 --- a/transforms/AspectTransform.cpp +++ b/transforms/AspectTransform.cpp @@ -38,6 +38,7 @@ namespace videocore { m_boundingHeight(boundingHeight), m_aspectMode(aspectMode), m_boundingBoxDirty(true), + m_hReverse(false), m_prevWidth(0), m_prevHeight(0) { @@ -75,6 +76,13 @@ namespace videocore { m_boundingBoxDirty = true; } + void + AspectTransform::setHReverse(bool hReverse) + { + m_hReverse = hReverse; + m_boundingBoxDirty = true; + } + void AspectTransform::pushBuffer(const uint8_t *const data, size_t size, @@ -107,7 +115,13 @@ namespace videocore { wfac = width*mult / float(m_boundingWidth); hfac = height*mult / float(m_boundingHeight); - m_scale = glm::vec3(wfac,hfac,1.f); + if (m_hReverse) { + m_scale = glm::vec3(-wfac,hfac,1.f); + } + else { + m_scale = glm::vec3(wfac,hfac,1.f); + } + m_boundingBoxDirty = false; } diff --git a/transforms/AspectTransform.h b/transforms/AspectTransform.h index e9dbbe94..53cd38d9 100644 --- a/transforms/AspectTransform.h +++ b/transforms/AspectTransform.h @@ -78,6 +78,7 @@ namespace videocore { */ void setBoundingBoxDirty() ; + void setHReverse(bool hReverse); public: /*! ITransform::setOutput */ @@ -103,6 +104,8 @@ namespace videocore { bool m_boundingBoxDirty; + bool m_hReverse; + }; } diff --git a/transforms/PositionTransform.cpp b/transforms/PositionTransform.cpp index f14d3c42..a311e97e 100644 --- a/transforms/PositionTransform.cpp +++ b/transforms/PositionTransform.cpp @@ -73,8 +73,8 @@ namespace videocore { m_height = height; m_positionIsDirty = true; } - void + PositionTransform::pushBuffer(const uint8_t *const data, size_t size, videocore::IMetadata &metadata) @@ -82,7 +82,6 @@ namespace videocore { auto output = m_output.lock(); if(output) { - if(m_positionIsDirty) { glm::mat4 mat(1.f); const float x (m_posX), y(m_posY), cw(m_contextWidth), ch(m_contextHeight), w(m_width), h(m_height); diff --git a/transforms/PositionTransform.h b/transforms/PositionTransform.h index aee03270..0d9acfd0 100644 --- a/transforms/PositionTransform.h +++ b/transforms/PositionTransform.h @@ -73,6 +73,7 @@ namespace videocore { void setSize(int width, int height); + public: /*! ITransform::setOutput */