mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-03 04:52:28 +00:00
avfvideosrc: improve timestamp code
Use a combination of the running time and CMClockGetTime from AVF to compute timestamps.
This commit is contained in:
parent
fd429d3233
commit
5496fd3e75
1 changed files with 37 additions and 26 deletions
|
@ -77,6 +77,7 @@ G_DEFINE_TYPE (GstAVFVideoSrc, gst_avf_video_src, GST_TYPE_PUSH_SRC);
|
||||||
AVCaptureInput *input;
|
AVCaptureInput *input;
|
||||||
AVCaptureVideoDataOutput *output;
|
AVCaptureVideoDataOutput *output;
|
||||||
AVCaptureDevice *device;
|
AVCaptureDevice *device;
|
||||||
|
CMClockRef inputClock;
|
||||||
|
|
||||||
dispatch_queue_t mainQueue;
|
dispatch_queue_t mainQueue;
|
||||||
dispatch_queue_t workerQueue;
|
dispatch_queue_t workerQueue;
|
||||||
|
@ -131,7 +132,6 @@ G_DEFINE_TYPE (GstAVFVideoSrc, gst_avf_video_src, GST_TYPE_PUSH_SRC);
|
||||||
- (BOOL)query:(GstQuery *)query;
|
- (BOOL)query:(GstQuery *)query;
|
||||||
- (GstStateChangeReturn)changeState:(GstStateChange)transition;
|
- (GstStateChangeReturn)changeState:(GstStateChange)transition;
|
||||||
- (GstFlowReturn)create:(GstBuffer **)buf;
|
- (GstFlowReturn)create:(GstBuffer **)buf;
|
||||||
- (void)timestampBuffer:(GstBuffer *)buf sampleBuffer:(CMSampleBufferRef)sampleBuffer;
|
|
||||||
- (void)updateStatistics;
|
- (void)updateStatistics;
|
||||||
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
- (void)captureOutput:(AVCaptureOutput *)captureOutput
|
||||||
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
|
@ -662,6 +662,7 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
latency = GST_CLOCK_TIME_NONE;
|
latency = GST_CLOCK_TIME_NONE;
|
||||||
startAVFTimestamp = GST_CLOCK_TIME_NONE;
|
startAVFTimestamp = GST_CLOCK_TIME_NONE;
|
||||||
startTimestamp = GST_CLOCK_TIME_NONE;
|
startTimestamp = GST_CLOCK_TIME_NONE;
|
||||||
|
inputClock = nil;
|
||||||
|
|
||||||
lastSampling = GST_CLOCK_TIME_NONE;
|
lastSampling = GST_CLOCK_TIME_NONE;
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -679,6 +680,7 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
bufQueueLock = nil;
|
bufQueueLock = nil;
|
||||||
[bufQueue release];
|
[bufQueue release];
|
||||||
bufQueue = nil;
|
bufQueue = nil;
|
||||||
|
inputClock = nil;
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
@ -753,6 +755,8 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
fromConnection:(AVCaptureConnection *)connection
|
fromConnection:(AVCaptureConnection *)connection
|
||||||
{
|
{
|
||||||
|
GstClockTime timestamp, duration;
|
||||||
|
|
||||||
[bufQueueLock lock];
|
[bufQueueLock lock];
|
||||||
|
|
||||||
if (stopRequest) {
|
if (stopRequest) {
|
||||||
|
@ -760,10 +764,16 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (inputClock == nil)
|
||||||
|
inputClock = ((AVCaptureInputPort *)connection.inputPorts[0]).clock;
|
||||||
|
[self getSampleBuffer:sampleBuffer timestamp:×tamp duration:&duration];
|
||||||
|
|
||||||
if ([bufQueue count] == BUFFER_QUEUE_SIZE)
|
if ([bufQueue count] == BUFFER_QUEUE_SIZE)
|
||||||
[bufQueue removeLastObject];
|
[bufQueue removeLastObject];
|
||||||
|
|
||||||
[bufQueue insertObject:(id)sampleBuffer
|
[bufQueue insertObject:@{@"sbuf": (id)sampleBuffer,
|
||||||
|
@"timestamp": @(timestamp),
|
||||||
|
@"duration": @(duration)}
|
||||||
atIndex:0];
|
atIndex:0];
|
||||||
|
|
||||||
[bufQueueLock unlockWithCondition:HAS_BUFFER_OR_STOP_REQUEST];
|
[bufQueueLock unlockWithCondition:HAS_BUFFER_OR_STOP_REQUEST];
|
||||||
|
@ -775,6 +785,7 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
CVImageBufferRef image_buf;
|
CVImageBufferRef image_buf;
|
||||||
CVPixelBufferRef pixel_buf;
|
CVPixelBufferRef pixel_buf;
|
||||||
size_t cur_width, cur_height;
|
size_t cur_width, cur_height;
|
||||||
|
GstClockTime timestamp, duration;
|
||||||
|
|
||||||
[bufQueueLock lockWhenCondition:HAS_BUFFER_OR_STOP_REQUEST];
|
[bufQueueLock lockWhenCondition:HAS_BUFFER_OR_STOP_REQUEST];
|
||||||
if (stopRequest) {
|
if (stopRequest) {
|
||||||
|
@ -782,7 +793,10 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
return GST_FLOW_FLUSHING;
|
return GST_FLOW_FLUSHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
sbuf = (CMSampleBufferRef) [bufQueue lastObject];
|
NSDictionary *dic = (NSDictionary *) [bufQueue lastObject];
|
||||||
|
sbuf = (CMSampleBufferRef) dic[@"sbuf"];
|
||||||
|
timestamp = (GstClockTime) [dic[@"timestamp"] longLongValue];
|
||||||
|
duration = (GstClockTime) [dic[@"duration"] longLongValue];
|
||||||
CFRetain (sbuf);
|
CFRetain (sbuf);
|
||||||
[bufQueue removeLastObject];
|
[bufQueue removeLastObject];
|
||||||
[bufQueueLock unlockWithCondition:
|
[bufQueueLock unlockWithCondition:
|
||||||
|
@ -812,7 +826,10 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
*buf = gst_core_media_buffer_new (sbuf, useVideoMeta);
|
*buf = gst_core_media_buffer_new (sbuf, useVideoMeta);
|
||||||
CFRelease (sbuf);
|
CFRelease (sbuf);
|
||||||
|
|
||||||
[self timestampBuffer:*buf sampleBuffer:sbuf];
|
GST_BUFFER_OFFSET (*buf) = offset++;
|
||||||
|
GST_BUFFER_OFFSET_END (*buf) = GST_BUFFER_OFFSET (buf) + 1;
|
||||||
|
GST_BUFFER_TIMESTAMP (*buf) = timestamp;
|
||||||
|
GST_BUFFER_DURATION (*buf) = duration;
|
||||||
|
|
||||||
if (doStats)
|
if (doStats)
|
||||||
[self updateStatistics];
|
[self updateStatistics];
|
||||||
|
@ -820,12 +837,15 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)timestampBuffer:(GstBuffer *)buf
|
- (void)getSampleBuffer:(CMSampleBufferRef)sbuf
|
||||||
sampleBuffer:(CMSampleBufferRef)sbuf
|
timestamp:(GstClockTime *)outTimestamp
|
||||||
|
duration:(GstClockTime *)outDuration
|
||||||
{
|
{
|
||||||
CMSampleTimingInfo time_info;
|
CMSampleTimingInfo time_info;
|
||||||
GstClockTime timestamp, duration;
|
GstClockTime timestamp, duration, inputClockNow, running_time;
|
||||||
CMItemCount num_timings;
|
CMItemCount num_timings;
|
||||||
|
GstClock *clock;
|
||||||
|
CMTime now;
|
||||||
|
|
||||||
timestamp = GST_CLOCK_TIME_NONE;
|
timestamp = GST_CLOCK_TIME_NONE;
|
||||||
duration = GST_CLOCK_TIME_NONE;
|
duration = GST_CLOCK_TIME_NONE;
|
||||||
|
@ -835,28 +855,19 @@ didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
|
||||||
duration = gst_util_uint64_scale (GST_SECOND,
|
duration = gst_util_uint64_scale (GST_SECOND,
|
||||||
time_info.duration.value, time_info.duration.timescale);
|
time_info.duration.value, time_info.duration.timescale);
|
||||||
|
|
||||||
if (offset == 0) {
|
now = CMClockGetTime(inputClock);
|
||||||
GstClock *clock;
|
inputClockNow = gst_util_uint64_scale (GST_SECOND,
|
||||||
|
now.value, now.timescale);
|
||||||
|
|
||||||
GST_OBJECT_LOCK (element);
|
GST_OBJECT_LOCK (element);
|
||||||
clock = GST_ELEMENT_CLOCK (element);
|
clock = GST_ELEMENT_CLOCK (element);
|
||||||
if (clock != NULL) {
|
running_time = gst_clock_get_time (clock) - element->base_time;
|
||||||
startTimestamp = gst_clock_get_time (clock) - element->base_time;
|
timestamp = running_time + (inputClockNow - timestamp);
|
||||||
}
|
GST_OBJECT_UNLOCK (element);
|
||||||
GST_OBJECT_UNLOCK (element);
|
|
||||||
|
|
||||||
startAVFTimestamp = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GST_CLOCK_TIME_IS_VALID (startAVFTimestamp) &&
|
|
||||||
GST_CLOCK_TIME_IS_VALID (startTimestamp))
|
|
||||||
timestamp = startTimestamp + (timestamp - startAVFTimestamp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_BUFFER_OFFSET (buf) = offset++;
|
*outTimestamp = timestamp;
|
||||||
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf) + 1;
|
*outDuration = duration;
|
||||||
GST_BUFFER_TIMESTAMP (buf) = timestamp;
|
|
||||||
GST_BUFFER_DURATION (buf) = duration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateStatistics
|
- (void)updateStatistics
|
||||||
|
|
Loading…
Reference in a new issue