2
0

WFCUI420VideoFrame.mm 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //
  2. // WFCUI420VideoFrame.m
  3. // WFChatUIKit
  4. //
  5. // Created by Rain on 2022/10/13.
  6. // Copyright © 2022 Wildfirechat. All rights reserved.
  7. //
  8. #import "WFCUI420VideoFrame.h"
  9. #import <libyuv.h>
  10. @interface WFCUI420VideoFrame ()
  11. @property (nonatomic) int width;
  12. @property (nonatomic) int height;
  13. @property (nonatomic) int dataLength;
  14. @property (nonatomic) UInt8 *data;
  15. @property (nonatomic) CFMutableDataRef cfData;
  16. @property (nonatomic) UInt8 *dataOfPlaneY;
  17. @property (nonatomic) UInt8 *dataOfPlaneU;
  18. @property (nonatomic) UInt8 *dataOfPlaneV;
  19. @property (nonatomic) int strideY;
  20. @property (nonatomic) int strideU;
  21. @property (nonatomic) int strideV;
  22. @end
  23. @implementation WFCUI420VideoFrame
  24. - (id)initWithWidth:(int)width height:(int)height
  25. {
  26. if (self = [super init]) {
  27. self.width = width;
  28. self.height = height;
  29. self.dataLength = self.width * self.height * 3 >> 1;
  30. self.cfData = CFDataCreateMutable(kCFAllocatorDefault, self.dataLength);
  31. self.data = CFDataGetMutableBytePtr(self.cfData);
  32. self.dataOfPlaneY = self.data;
  33. self.dataOfPlaneU = self.dataOfPlaneY + self.width * self.height;
  34. self.dataOfPlaneV = self.dataOfPlaneU + self.width * self.height / 4;
  35. self.strideY = self.width;
  36. self.strideU = self.width >> 1;
  37. self.strideV = self.width >> 1;
  38. }
  39. return self;
  40. }
  41. - (void)fromBytes:(NSData *)data {
  42. memcpy(self.data, data.bytes, self.dataLength);
  43. }
  44. - (NSData *)toBytes {
  45. NSData *data = [NSData dataWithBytes:self.data length:self.dataLength];
  46. return data;
  47. }
  48. - (CVPixelBufferRef)toPixelBuffer {
  49. CVPixelBufferRef pixelBuffer = NULL;
  50. NSDictionary *pixelBufferAttributes = [NSDictionary dictionaryWithObjectsAndKeys:
  51. [NSDictionary dictionary], (id)kCVPixelBufferIOSurfacePropertiesKey,
  52. nil];
  53. CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault,
  54. self.width,
  55. self.height,
  56. kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
  57. (__bridge CFDictionaryRef)pixelBufferAttributes,
  58. &pixelBuffer);
  59. if (result != kCVReturnSuccess) {
  60. return NULL;
  61. }
  62. result = CVPixelBufferLockBaseAddress(pixelBuffer, 0);
  63. if (result != kCVReturnSuccess) {
  64. CFRelease(pixelBuffer);
  65. return NULL;
  66. }
  67. uint8 *dstY = (uint8 *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
  68. int dstStrideY = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
  69. uint8* dstUV = (uint8*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
  70. int dstStrideUV = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
  71. int ret = libyuv::I420ToNV12(self.dataOfPlaneY, self.strideY,
  72. self.dataOfPlaneU, self.strideU,
  73. self.dataOfPlaneV, self.strideV,
  74. dstY, dstStrideY, dstUV, dstStrideUV,
  75. self.width, self.height);
  76. CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
  77. if (ret) {
  78. CFRelease(pixelBuffer);
  79. return NULL;
  80. }
  81. return pixelBuffer;
  82. }
  83. - (void) dealloc {
  84. CFRelease(self.cfData);
  85. }
  86. @end