- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在使用 PBJVision实现点击录制视频功能。该库尚不支持方向,因此我正在尝试对其进行设计。据我所知,有三种旋转视频的方法-我需要帮助来确定最佳前进方式以及如何实现它.请注意,旋转可能发生在点击记录段之间。因此在录制 session 中,方向被锁定为用户点击按钮时的方向。下次用户点击按钮进行录制时,它应该将方向重新设置为设备的方向(因此生成的视频显示为右侧向上)。
issue page on GitHub as well 中概述了这些方法
方法一使用 setVideoOrientation:
旋转 AVCaptureConnection
- 这会导致视频预览在每次切换时闪烁,因为这似乎切换了实际的硬件。不酷, Not Acceptable 。
方法二在用于编写视频的 AVAssetWriterInput
对象上设置 transform
属性。问题是,一旦 Assets 编写者开始编写,transform
属性就无法更改,因此这仅适用于视频的第一段。
方法三使用类似这样的方法旋转正在附加的图像缓冲区:How to directly rotate CVImageBuffer image in IOS 4 without converting to UIImage?但它一直在崩溃,我什至不确定我是否在咆哮正确的树。抛出一个异常,除了我错误地使用了 vImageRotate90_ARGB8888
函数之外,我无法真正追溯到它。
在我上面链接的 GitHub 问题页面上,解释更详细一些。欢迎任何建议 - 老实说,我在 AVFoundation 方面经验不足,所以我希望有一些我什至不知道的神奇方法来做到这一点!
最佳答案
根据 Apple's documentation,方法 1 不是首选方法(“物理旋转缓冲区确实会带来性能成本,因此只有在必要时才请求旋转”)。方法 2 对我有用,但如果我在不支持转换“元数据”的应用程序上播放我的视频,则视频不会正确旋转。方法三是我做的。
在您尝试将图像数据直接从 vImageRotate...
传递到 AVAssetWriterInputPixelBufferAdaptor
之前,我认为它会崩溃。您必须先创建一个 CVPixelBufferRef
。这是我的代码:
在 captureOutput:didOutputSampleBuffer:fromConnection:
内部,我在将框架写入适配器之前旋转它:
if ([self.videoWriterInput isReadyForMoreMediaData])
{
// Rotate buffer first and then write to adaptor
CMTime sampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
CVPixelBufferRef rotatedBuffer = [self correctBufferOrientation:sampleBuffer];
[self.videoWriterInputAdaptor appendPixelBuffer:rotatedBuffer withPresentationTime:sampleTime];
CVBufferRelease(rotatedBuffer);
}
执行vImage旋转的引用函数是:
/* rotationConstant:
* 0 -- rotate 0 degrees (simply copy the data from src to dest)
* 1 -- rotate 90 degrees counterclockwise
* 2 -- rotate 180 degress
* 3 -- rotate 270 degrees counterclockwise
*/
- (CVPixelBufferRef)rotateBuffer:(CMSampleBufferRef)sampleBuffer withConstant:(uint8_t)rotationConstant
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(imageBuffer, 0);
OSType pixelFormatType = CVPixelBufferGetPixelFormatType(imageBuffer);
NSAssert(pixelFormatType == kCVPixelFormatType_32ARGB, @"Code works only with 32ARGB format. Test/adapt for other formats!");
const size_t kAlignment_32ARGB = 32;
const size_t kBytesPerPixel_32ARGB = 4;
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
size_t width = CVPixelBufferGetWidth(imageBuffer);
size_t height = CVPixelBufferGetHeight(imageBuffer);
BOOL rotatePerpendicular = (rotateDirection == 1) || (rotateDirection == 3); // Use enumeration values here
const size_t outWidth = rotatePerpendicular ? height : width;
const size_t outHeight = rotatePerpendicular ? width : height;
size_t bytesPerRowOut = kBytesPerPixel_32ARGB * ceil(outWidth * 1.0 / kAlignment_32ARGB) * kAlignment_32ARGB;
const size_t dstSize = bytesPerRowOut * outHeight * sizeof(unsigned char);
void *srcBuff = CVPixelBufferGetBaseAddress(imageBuffer);
unsigned char *dstBuff = (unsigned char *)malloc(dstSize);
vImage_Buffer inbuff = {srcBuff, height, width, bytesPerRow};
vImage_Buffer outbuff = {dstBuff, outHeight, outWidth, bytesPerRowOut};
uint8_t bgColor[4] = {0, 0, 0, 0};
vImage_Error err = vImageRotate90_ARGB8888(&inbuff, &outbuff, rotationConstant, bgColor, 0);
if (err != kvImageNoError)
{
NSLog(@"%ld", err);
}
CVPixelBufferUnlockBaseAddress(imageBuffer, 0);
CVPixelBufferRef rotatedBuffer = NULL;
CVPixelBufferCreateWithBytes(NULL,
outWidth,
outHeight,
pixelFormatType,
outbuff.data,
bytesPerRowOut,
freePixelBufferDataAfterRelease,
NULL,
NULL,
&rotatedBuffer);
return rotatedBuffer;
}
void freePixelBufferDataAfterRelease(void *releaseRefCon, const void *baseAddress)
{
// Free the memory we malloced for the vImage rotation
free((void *)baseAddress);
}
注意:您可能喜欢为 rotationConstant
使用枚举。类似这样的东西(不要用 MOVRotateDirectionUnknown
调用这个函数):
typedef NS_ENUM(uint8_t, MOVRotateDirection)
{
MOVRotateDirectionNone = 0,
MOVRotateDirectionCounterclockwise90,
MOVRotateDirectionCounterclockwise180,
MOVRotateDirectionCounterclockwise270,
MOVRotateDirectionUnknown
};
注意:如果您需要IOSurface
支持,您应该使用CVPixelBufferCreate
而不是CVPixelBufferCreateWithBytes
并直接将字节数据传递给它:
NSDictionary *pixelBufferAttributes = @{ (NSString *)kCVPixelBufferIOSurfacePropertiesKey : @{} };
CVPixelBufferCreate(kCFAllocatorDefault,
outWidth,
outHeight,
pixelFormatType,
(__bridge CFDictionaryRef)(pixelBufferAttributes),
&rotatedBuffer);
CVPixelBufferLockBaseAddress(rotatedBuffer, 0);
uint8_t *dest = CVPixelBufferGetBaseAddress(rotatedBuffer);
memcpy(dest, outbuff.data, bytesPerRowOut * outHeight);
CVPixelBufferUnlockBaseAddress(rotatedBuffer, 0);
关于ios - 旋转视频而不旋转 AVCaptureConnection 并且在 AVAssetWriter session 中间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22745824/
有人知道如何在 AVFoundation 中使用 AVAssetWriter 将未压缩的帧存储到 mov 中吗?对于 ProRes4444 内容,我实际上使用了以下片段: NSDictionary *
我在iOS上使用AVAssetWriter编码MP4视频。我目前正在使用AVAssetWriterInputPixelBufferAdaptor传递数据,但是在这方面我很灵活。 如何指定哪些输入框是关
我使用以下代码附加PixelBuffer,但输出视频是黑屏(CIImage 是正常的)。我认为问题出现在 newPixelBuffer 中。 func recordRealTimeFilterVide
为什么当您加载纵向 JPGS 并尝试使用 AVAssetWriter 时,生成的 mov 文件旋转了 90? 其他人看到了吗? 最佳答案 如果肖像 jpg 是在 iphone 上制作的,则它们的原始像
此代码适用于从图像创建视频。 AVAssetWritter 工作正常,没有错误并导出输出视频 - (.mov)。但在某些图像大小的情况下它会失败。120 x 160 - 失败180 x 640、240
我正在尝试将多个视频文件合并到一个具有特定编解码器设置的文件中。我曾经为此使用 AVAssetExportSession,但现在我需要比 AVAssetExportSession 提供更多的编解码器控
我正在 iOS 上编写一个视频编辑小应用。我关注了 this question 中评价最高的答案想用AVAssetwriter,最后写入还是失败了。当我进入 complete 回调时 [videoWr
创建 assetwriter 后,我的 friend 在他的设备上收到此错误 - 日志:AVAssetWriter:0x1e051900,outputURL = file://localhost/va
我有以下代码在 AVAssetWriter 中写入日期元数据,这在 iOS 13 中完全错误。需要知道这是 iOS 13 错误还是我做错了什么。 private var metadataIt
我正在完成一个将电影保存到相册的 iPhone 应用程序。电影源是一组图像。我用它制作电影并将它们很好地放入相册,但它总是在开始时有一个额外的绿色框架。 有什么想法吗? 我重新阅读了 Apple
我正在尝试使用 OSX AVAsset 类从电影文件中读取视频帧,调整颜色,然后将它们写出到新的电影文件中。我已经完成了所有工作,除了出于某种奇怪的原因,当我正在阅读以每秒 29.97 帧播放的视频时
我有几种方法可以将 mov 文件中的视频写入临时目录,但在大约 15 秒后。我收到错误: 收到内存警告。 收到内存警告。 收到内存警告。 收到内存警告。 然后应用程序崩溃了。我被卡住了,不知道出了什么
你好,我是 ios 开发的新手,我遇到了一些问题 我做了一些 AVAssetWriter 的设置,比如对象(我用它来写像素图作为视频的帧 - 它工作正常) self.assetWriter =
我录制音频和视频文件。用户可以只从视频切换到音频,也可以从音频切换到视频。但是当我从音频切换到视频时,第一帧是黑色的。 切换 func switch_to_audio(){ capture_s
我正在使用 AVAssetWriter 通过委托(delegate)从 ARSession 写入视频帧。 func session(_ session: ARSession, didUpdate fr
我正在开发一个使用 AVAssetWriter 录制视频的应用程序(源媒体是从 captureOutput(_ output: AVCaptureOutput, didOutput sampleBuf
我正在制作一个录制视频的应用程序。到目前为止,我已经能够使用 AVCaptureMovieFileOutput 成功录制视频和音频,但是,我现在需要实时编辑视频帧以将一些数据叠加到视频上。我开始切换到
是否可以在 iPhone 上使用 avassetwriter 合成绿屏图像——绿色背景下的动画 Actor 和背景照片并制作视频。 我有一个应用程序可以在绿色背景下创建动画角色的一系列屏幕截图。我想将
我正在使用 AVAssetWriter 将音频(和/或视频)写入 quicktime 电影格式。如何在不停止 session (即继续记录)的情况下定期(每隔几分钟)保存(或备份)此文件? 这是我在录
如果我包含的图像没有填满整个渲染区域,我用 AVAssetWriter 编写的每个文件都有黑色背景。有什么方法可以写透明吗?这是我用来获取像素缓冲区的方法: - (CVPixelBufferRef)p
我是一名优秀的程序员,十分优秀!