forked from AgoraIO/API-Examples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMediaUtils.m
More file actions
89 lines (71 loc) · 3.07 KB
/
MediaUtils.m
File metadata and controls
89 lines (71 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//
// MediaUtils.m
// APIExample
//
// Created by Arlin on 2022/4/12.
// Copyright © 2022 Agora Corp. All rights reserved.
//
#import "MediaUtils.h"
#import <CoreImage/CoreImage.h>
@implementation MediaUtils
+ (UIImage *)i420ToImage:(void *)srcY srcU:(void *)srcU srcV:(void *)srcV width:(int)width height:(int)height {
int size = width * height * 3 / 2;
int yLength = width * height;
int uLength = yLength / 4;
unsigned char *buf = (unsigned char *)malloc(size);
memcpy(buf, srcY, yLength);
memcpy(buf + yLength, srcU, uLength);
memcpy(buf + yLength + uLength, srcV, uLength);
unsigned char * NV12buf = (unsigned char *)malloc(size);
[self yuv420p_to_nv12:buf nv12:NV12buf width:width height:height];
int w = width;
int h = height;
NSDictionary *pixelAttributes = @{(NSString*)kCVPixelBufferIOSurfacePropertiesKey:@{}};
CVPixelBufferRef pixelBuffer = NULL;
CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault,
w,
h,
kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
(__bridge CFDictionaryRef)(pixelAttributes),
&pixelBuffer);
if (result != kCVReturnSuccess) {
NSLog(@"Unable to create cvpixelbuffer %d", result);
return nil;
}
CVPixelBufferLockBaseAddress(pixelBuffer,0);
void *yDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
// Here y_ch0 is Y-Plane of YUV(NV12) data.
unsigned char *y_ch0 = NV12buf;
unsigned char *y_ch1 = NV12buf + w * h;
memcpy(yDestPlane, y_ch0, w * h);
void *uvDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
// Here y_ch1 is UV-Plane of YUV(NV12) data.
memcpy(uvDestPlane, y_ch1, w * h * 0.5);
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
// CIImage Conversion
CIImage *coreImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
CIContext *temporaryContext = [CIContext contextWithOptions:nil];
CGImageRef videoImage = [temporaryContext createCGImage:coreImage
fromRect:CGRectMake(0, 0, w, h)];
UIImage *finalImage = [[UIImage alloc] initWithCGImage:videoImage
scale:1.0
orientation:UIImageOrientationRight];
CVPixelBufferRelease(pixelBuffer);
CGImageRelease(videoImage);
return finalImage;
}
+ (void)yuv420p_to_nv12:(unsigned char*)yuv420p nv12:(unsigned char*)nv12 width:(int)width height:(int)height {
int i, j;
int y_size = width * height;
unsigned char* y = yuv420p;
unsigned char* u = yuv420p + y_size;
unsigned char* v = yuv420p + y_size * 5 / 4;
unsigned char* y_tmp = nv12;
unsigned char* uv_tmp = nv12 + y_size;
memcpy(y_tmp, y, y_size);
for (j = 0, i = 0; j < y_size * 0.5; j += 2, i++) {
uv_tmp[j] = u[i];
uv_tmp[j+1] = v[i];
}
}
@end