Commit c5fd3b92 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

video: remove buffer padding

This patch fix video rendering when pixelbuffer have a padding.

Change-Id: I9ab48109c5ad6400ad8da4037f6f508f3db84025
Reviewed-by: Philippe Gorley's avatarPhilippe Gorley <philippe.gorley@savoirfairelinux.com>
parent 29519a1a
...@@ -232,6 +232,8 @@ SET(ringclient_OTHERS ...@@ -232,6 +232,8 @@ SET(ringclient_OTHERS
src/AppDelegate.mm src/AppDelegate.mm
src/AppDelegate.h src/AppDelegate.h
src/Constants.h src/Constants.h
src/VideoCommon.h
src/VideoCommon.mm
src/INDSequentialTextSelectionManager.mm src/INDSequentialTextSelectionManager.mm
src/INDSequentialTextSelectionManager.h src/INDSequentialTextSelectionManager.h
src/delegates/ImageManipulationDelegate.mm src/delegates/ImageManipulationDelegate.mm
......
...@@ -48,6 +48,7 @@ extern "C" { ...@@ -48,6 +48,7 @@ extern "C" {
#import "views/IconButton.h" #import "views/IconButton.h"
#import "utils.h" #import "utils.h"
#import "views/CallMTKView.h" #import "views/CallMTKView.h"
#import "VideoCommon.h"
@interface RendererConnectionsHolder : NSObject @interface RendererConnectionsHolder : NSObject
...@@ -613,132 +614,15 @@ CVPixelBufferRef pixelBufferPreview; ...@@ -613,132 +614,15 @@ CVPixelBufferRef pixelBufferPreview;
} }
-(CVPixelBufferRef) getBufferForPreviewFromFrame:(const AVFrame*)frame { -(CVPixelBufferRef) getBufferForPreviewFromFrame:(const AVFrame*)frame {
if(!frame || !frame->data[0] || !frame->data[1]) { [VideoCommon fillPixelBuffr:&pixelBufferPreview fromFrame:frame bufferPool:&pixelBufferPoolPreview];
return nil; CVPixelBufferRef buffer = pixelBufferPreview;
} return buffer;
CVReturn theError;
bool createPool = false;
if (!pixelBufferPoolPreview) {
createPool = true;
} else {
NSDictionary* atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetAttributes(pixelBufferPoolPreview);
if(!atributes)
atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(pixelBufferPoolPreview);
int width = [[atributes objectForKey:(NSString*)kCVPixelBufferWidthKey] intValue];
int height = [[atributes objectForKey:(NSString*)kCVPixelBufferHeightKey] intValue];
if (width != frame->width || height != frame->height) {
createPool = true;
}
}
if (createPool) {
CVPixelBufferPoolRelease(pixelBufferPoolPreview);
CVPixelBufferRelease(pixelBufferPreview);
pixelBufferPreview = nil;
pixelBufferPoolPreview = nil;
NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
[attributes setObject:[NSNumber numberWithInt:frame->width] forKey: (NSString*)kCVPixelBufferWidthKey];
[attributes setObject:[NSNumber numberWithInt:frame->height] forKey: (NSString*)kCVPixelBufferHeightKey];
[attributes setObject:@(frame->linesize[0]) forKey:(NSString*)kCVPixelBufferBytesPerRowAlignmentKey];
[attributes setObject:[NSDictionary dictionary] forKey:(NSString*)kCVPixelBufferIOSurfacePropertiesKey];
theError = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (__bridge CFDictionaryRef) attributes, &pixelBufferPoolPreview);
if (theError != kCVReturnSuccess) {
NSLog(@"CVPixelBufferPoolCreate Failed");
return nil;
}
}
if(!pixelBufferPreview) {
theError = CVPixelBufferPoolCreatePixelBuffer(NULL, pixelBufferPoolPreview, &pixelBufferPreview);
if(theError != kCVReturnSuccess) {
NSLog(@"CVPixelBufferPoolCreatePixelBuffer Failed");
return nil;
}
}
theError = CVPixelBufferLockBaseAddress(pixelBufferPreview, 0);
if (theError != kCVReturnSuccess) {
NSLog(@"lock error");
return nil;
}
size_t bytePerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferPreview, 0);
size_t bytesPerRowUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferPreview, 1);
void* base = CVPixelBufferGetBaseAddressOfPlane(pixelBufferPreview, 0);
memcpy(base, frame->data[0], bytePerRowY * frame->height);
base = CVPixelBufferGetBaseAddressOfPlane(pixelBufferPreview, 1);
memcpy(base, frame->data[1], bytesPerRowUV * frame->height/2);
CVPixelBufferUnlockBaseAddress(pixelBufferPreview, 0);
return pixelBufferPreview;
} }
-(CVPixelBufferRef) getBufferForDistantViewFromFrame:(const AVFrame*)frame { -(CVPixelBufferRef) getBufferForDistantViewFromFrame:(const AVFrame*)frame {
if(!frame || !frame->data[0] || !frame->data[1]) { [VideoCommon fillPixelBuffr:&pixelBufferDistantView fromFrame:frame bufferPool:&pixelBufferPoolDistantView];
return nil; CVPixelBufferRef buffer = pixelBufferDistantView;
} return buffer;
CVReturn theError;
bool createPool = false;
if (!pixelBufferPoolDistantView){
createPool = true;
}
NSDictionary* atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(pixelBufferPoolDistantView);
if(!atributes)
atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(pixelBufferPoolDistantView);
int width = [[atributes objectForKey:(NSString*)kCVPixelBufferWidthKey] intValue];
int height = [[atributes objectForKey:(NSString*)kCVPixelBufferHeightKey] intValue];
if (width != frame->width || height != frame->height) {
createPool = true;
}
if (createPool) {
CVPixelBufferPoolRelease(pixelBufferPoolDistantView);
CVPixelBufferRelease(pixelBufferDistantView);
pixelBufferDistantView = nil;
pixelBufferPoolDistantView = nil;
NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
[attributes setObject:[NSNumber numberWithInt:frame->width] forKey: (NSString*)kCVPixelBufferWidthKey];
[attributes setObject:[NSNumber numberWithInt:frame->height] forKey: (NSString*)kCVPixelBufferHeightKey];
[attributes setObject:@(frame->linesize[0]) forKey:(NSString*)kCVPixelBufferBytesPerRowAlignmentKey];
[attributes setObject:[NSDictionary dictionary] forKey:(NSString*)kCVPixelBufferIOSurfacePropertiesKey];
theError = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (__bridge CFDictionaryRef) attributes, &pixelBufferPoolDistantView);
if (theError != kCVReturnSuccess) {
return nil;
NSLog(@"CVPixelBufferPoolCreate Failed");
}
}
if(!pixelBufferDistantView) {
theError = CVPixelBufferPoolCreatePixelBuffer(NULL, pixelBufferPoolDistantView, &pixelBufferDistantView);
if(theError != kCVReturnSuccess) {
return nil;
NSLog(@"CVPixelBufferPoolCreatePixelBuffer Failed");
}
}
theError = CVPixelBufferLockBaseAddress(pixelBufferDistantView, 0);
if (theError != kCVReturnSuccess) {
return nil;
NSLog(@"lock error");
}
size_t bytePerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferDistantView, 0);
size_t bytesPerRowUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferDistantView, 1);
void* base = CVPixelBufferGetBaseAddressOfPlane(pixelBufferDistantView, 0);
memcpy(base, frame->data[0], bytePerRowY * frame->height);
base = CVPixelBufferGetBaseAddressOfPlane(pixelBufferDistantView, 1);
uint32_t size = frame->linesize[1] * frame->height / 2;
uint8_t* dstData = new uint8_t[2 * size];
uint8_t * firstData = new uint8_t[size];
memcpy(firstData, frame->data[1], size);
uint8_t * secondData = new uint8_t[size];
memcpy(secondData, frame->data[2], size);
for (int i = 0; i < 2 * size; i++){
if (i % 2 == 0){
dstData[i] = firstData[i/2];
}else {
dstData[i] = secondData[i/2];
}
}
memcpy(base, dstData, bytesPerRowUV * frame->height/2);
CVPixelBufferUnlockBaseAddress(pixelBufferDistantView, 0);
free(dstData);
free(firstData);
free(secondData);
return pixelBufferDistantView;
} }
- (void) initFrame - (void) initFrame
......
/*
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
struct AVFrame;
@interface VideoCommon : NSObject
+ (void)copyLineByLineSrc:(uint8_t*)src
toDest:(uint8_t*)dest
srcLinesize:(size_t)srcLinesize
destLinesize:(size_t)destLinesize
height:(size_t)height;
+ (void) fillPixelBuffr:(CVPixelBufferRef *)pixelBuffer
fromFrame:(const AVFrame*)frame
bufferPool:(CVPixelBufferPoolRef *)pixelBufferPool;
@end
/*
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "VideoCommon.h"
extern "C" {
#import <libavutil/frame.h>
}
@implementation VideoCommon
+ (void)copyLineByLineSrc:(uint8_t*)src
toDest:(uint8_t*)dest
srcLinesize:(size_t)srcLinesize
destLinesize:(size_t)destLinesize
height:(size_t)height {
for (size_t i = 0; i < height ; i++) {
memcpy(dest, src, srcLinesize);
dest = dest + destLinesize;
src = src + srcLinesize;
}
}
+ (void) fillPixelBuffr:(CVPixelBufferRef &)pixelBuffer
fromFrame:(const AVFrame*)frame
bufferPool:(CVPixelBufferPoolRef &)pixelBufferPool {
if(!frame || !frame->data[0] || !frame->data[1]) {
return;
}
CVReturn theError;
bool createPool = false;
if (!pixelBufferPool) {
createPool = true;
} else {
NSDictionary* atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetAttributes(pixelBufferPool);
if(!atributes)
atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(pixelBufferPool);
int width = [[atributes objectForKey:(NSString*)kCVPixelBufferWidthKey] intValue];
int height = [[atributes objectForKey:(NSString*)kCVPixelBufferHeightKey] intValue];
if (width != frame->width || height != frame->height) {
createPool = true;
}
}
if (createPool) {
CVPixelBufferPoolRelease(pixelBufferPool);
CVPixelBufferRelease(pixelBuffer);
pixelBuffer = nil;
pixelBufferPool = nil;
NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
[attributes setObject:[NSNumber numberWithInt:frame->width] forKey: (NSString*)kCVPixelBufferWidthKey];
[attributes setObject:[NSNumber numberWithInt:frame->height] forKey: (NSString*)kCVPixelBufferHeightKey];
[attributes setObject:@(frame->linesize[0]) forKey:(NSString*)kCVPixelBufferBytesPerRowAlignmentKey];
[attributes setObject:[NSDictionary dictionary] forKey:(NSString*)kCVPixelBufferIOSurfacePropertiesKey];
theError = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (__bridge CFDictionaryRef) attributes, &pixelBufferPool);
if (theError != kCVReturnSuccess) {
NSLog(@"CVPixelBufferPoolCreate Failed");
return;
}
}
if(!pixelBuffer) {
theError = CVPixelBufferPoolCreatePixelBuffer(NULL, pixelBufferPool, &pixelBuffer);
if(theError != kCVReturnSuccess) {
NSLog(@"CVPixelBufferPoolCreatePixelBuffer Failed");
return;
}
}
theError = CVPixelBufferLockBaseAddress(pixelBuffer, 0);
if (theError != kCVReturnSuccess) {
NSLog(@"lock error");
return;
}
size_t bytePerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
size_t bytesPerRowUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
uint8_t* base = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0));
if (bytePerRowY == frame->linesize[0]) {
memcpy(base, frame->data[0], bytePerRowY * frame->height);
} else {
[VideoCommon copyLineByLineSrc: frame->data[0]
toDest: base
srcLinesize: frame->linesize[0]
destLinesize: bytePerRowY
height: frame->height];
}
if ((AVPixelFormat)frame->format == AV_PIX_FMT_NV12) {
base = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1));
if (bytesPerRowUV == frame->linesize[0]) {
memcpy(base, frame->data[1], bytesPerRowUV * frame->height/2);
} else {
[VideoCommon copyLineByLineSrc: frame->data[1]
toDest: base
srcLinesize: frame->linesize[0]
destLinesize: bytesPerRowUV
height: frame->height/2];
}
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
return;
}
base = static_cast<uint8_t*>(CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1));
for(size_t i = 0; i < frame->height / 2 * bytesPerRowUV / 2; i++ ){
*base++ = frame->data[1][i];
*base++ = frame->data[2][i];
}
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}
@end
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#import "VideoPrefsVC.h" #import "VideoPrefsVC.h"
#import "views/CallMTKView.h" #import "views/CallMTKView.h"
#import "AppDelegate.h" #import "AppDelegate.h"
#import "VideoCommon.h"
#import <QuartzCore/QuartzCore.h> #import <QuartzCore/QuartzCore.h>
...@@ -28,7 +29,6 @@ ...@@ -28,7 +29,6 @@
extern "C" { extern "C" {
#import "libavutil/frame.h" #import "libavutil/frame.h"
#import "libavutil/display.h"
} }
@interface VideoPrefsVC () @interface VideoPrefsVC ()
...@@ -234,61 +234,9 @@ std::string currentVideoDevice; ...@@ -234,61 +234,9 @@ std::string currentVideoDevice;
} }
-(CVPixelBufferRef) getBufferForPreviewFromFrame:(const AVFrame*)frame { -(CVPixelBufferRef) getBufferForPreviewFromFrame:(const AVFrame*)frame {
if(!frame || !frame->data[0] || !frame->data[1]) { [VideoCommon fillPixelBuffr:&pixelBuffer fromFrame:frame bufferPool:&pixelBufferPool];
return nil; CVPixelBufferRef buffer = pixelBuffer;
} return buffer;
CVReturn theError;
bool createPool = false;
if (!pixelBufferPool) {
createPool = true;
} else {
NSDictionary* atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetAttributes(pixelBufferPool);
if(!atributes)
atributes = (__bridge NSDictionary*)CVPixelBufferPoolGetPixelBufferAttributes(pixelBufferPool);
int width = [[atributes objectForKey:(NSString*)kCVPixelBufferWidthKey] intValue];
int height = [[atributes objectForKey:(NSString*)kCVPixelBufferHeightKey] intValue];
if (width != frame->width || height != frame->height) {
createPool = true;
}
}
if (createPool) {
CVPixelBufferPoolRelease(pixelBufferPool);
CVPixelBufferRelease(pixelBuffer);
pixelBuffer = nil;
pixelBufferPool = nil;
NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
[attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];
[attributes setObject:[NSNumber numberWithInt:frame->width] forKey: (NSString*)kCVPixelBufferWidthKey];
[attributes setObject:[NSNumber numberWithInt:frame->height] forKey: (NSString*)kCVPixelBufferHeightKey];
[attributes setObject:@(frame->linesize[0]) forKey:(NSString*)kCVPixelBufferBytesPerRowAlignmentKey];
[attributes setObject:[NSDictionary dictionary] forKey:(NSString*)kCVPixelBufferIOSurfacePropertiesKey];
theError = CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (__bridge CFDictionaryRef) attributes, &pixelBufferPool);
if (theError != kCVReturnSuccess) {
NSLog(@"CVPixelBufferPoolCreate Failed");
return nil;
}
}
if(!pixelBuffer) {
NSMutableDictionary* attributes = [NSMutableDictionary dictionary];
theError = CVPixelBufferPoolCreatePixelBuffer(NULL, pixelBufferPool, &pixelBuffer);
if(theError != kCVReturnSuccess) {
NSLog(@"CVPixelBufferPoolCreatePixelBuffer Failed");
return nil;
}
}
theError = CVPixelBufferLockBaseAddress(pixelBuffer, 0);
if (theError != kCVReturnSuccess) {
NSLog(@"lock error");
return nil;
}
size_t bytePerRowY = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
size_t bytesPerRowUV = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
void* base = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
memcpy(base, frame->data[0], bytePerRowY * frame->height);
base = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
memcpy(base, frame->data[1], bytesPerRowUV * frame->height/2);
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
return pixelBuffer;
} }
-(void)addDevices { -(void)addDevices {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment