Я забираю канал камеры и записываю его в кино. Проблема, с которой я столкнулся, заключается в том, что после экспорта у фильма есть пара черных секунд перед ним (относительно фактического времени начала записи).AVAssetWriter/AVAssetWriterInputPixelBufferAdaptor - черные кадры и частота кадров
Я думаю, это связано с [self.assetWriter startSessionAtSourceTime:kCMTimeZero];
У меня было полурабочее решение, имея переменную frameStart, которая только что подсчитана вверх в методе делегата samplebuffer.
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
frameStart++;
if (self.startRecording == YES) {
static int64_t frameNumber = 0;
if(self.assetWriterInput.readyForMoreMediaData) {
[self.pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:CMTimeMake(frameNumber, 25)];
}
frameNumber++;
}
}
и затем вызвать этот метод, когда пользователь нажал кнопку:
[self.assetWriter startSessionAtSourceTime:CMTimeMake(frameStart,25)];
это работает. но только один раз ... если я хочу записать второй фильм, черные кадры снова вернутся.
Кроме того, когда я смотрю на выведенный фильм, частота кадров составляет 25 кадров в секунду, как я этого хочу. но видео выглядит так, как будто оно ускоряется. как будто между кадрами недостаточно места. Таким образом, фильм играет примерно в два раза быстрее.
NSDictionary *outputSettings = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:640], AVVideoWidthKey, [NSNumber numberWithInt:480], AVVideoHeightKey, AVVideoCodecH264, AVVideoCodecKey, nil];
self.assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:outputSettings];
self.assetWriterInput.expectsMediaDataInRealTime = YES;
Это на самом деле очень близко. У меня только один вопрос. Как я могу получить метку времени при нажатии кнопки? Прямо сейчас у меня есть переменная CMTime 'lastTimestamp', которая продолжает получать метку времени из последнего кадра в методе connectOutput: (AVCaptureOutput *) captureOutput didOutputSampleBuffer: (CMSampleBufferRef) sampleBuffer fromConnection: (AVCaptureConnection *). Затем, когда пользователь нажимает кнопку, я делаю [self.assetWriter startSessionAtSourceTime: self.latestFrameTimeStamp]; 'Это работает, но я предполагаю, что должен быть лучший способ. –
Это на самом деле то, что я делаю: начните сеанс записи с отметки времени первого образца, входящего после нажатия пользователем кнопки. Если вы действительно принимаете момент, когда пользователь нажал кнопку в качестве начальной точки, вы могли бы получить несколько пустых кадров в начале видео из-за задержки захвата. –
Но как бы получить этот первый образец? Потому что образец может быть получен только в методе делегирования буфера выборки правильно? предположим, что у меня есть метод '- (void) buttonPressed'. И там я вызываю этот метод '[self.assetWriter startSessionAtSourceTime: timestamp]; 'Как я могу получить последнюю временную метку из метода делегата в методе нажатия кнопки? (в хорошем смысле) –