qtkitvideosrc: simplify timestamping algorithm
Aligning timestamps on duration boundaries, skipping frames and so forth are clearly things that fall outside the scope of a video source.
This commit is contained in:
parent
3ba76f825d
commit
b39609b405
@ -112,7 +112,6 @@ static GstPushSrcClass * parent_class;
|
|||||||
gint width, height;
|
gint width, height;
|
||||||
GstClockTime duration;
|
GstClockTime duration;
|
||||||
guint64 offset;
|
guint64 offset;
|
||||||
GstClockTime prev_ts;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init;
|
- (id)init;
|
||||||
@ -130,7 +129,7 @@ static GstPushSrcClass * parent_class;
|
|||||||
- (BOOL)query:(GstQuery *)query;
|
- (BOOL)query:(GstQuery *)query;
|
||||||
- (GstStateChangeReturn)changeState:(GstStateChange)transition;
|
- (GstStateChangeReturn)changeState:(GstStateChange)transition;
|
||||||
- (GstFlowReturn)create:(GstBuffer **)buf;
|
- (GstFlowReturn)create:(GstBuffer **)buf;
|
||||||
- (BOOL)timestampBuffer:(GstBuffer *)buf;
|
- (void)timestampBuffer:(GstBuffer *)buf;
|
||||||
- (void)captureOutput:(QTCaptureOutput *)captureOutput
|
- (void)captureOutput:(QTCaptureOutput *)captureOutput
|
||||||
didOutputVideoFrame:(CVImageBufferRef)videoFrame
|
didOutputVideoFrame:(CVImageBufferRef)videoFrame
|
||||||
withSampleBuffer:(QTSampleBuffer *)sampleBuffer
|
withSampleBuffer:(QTSampleBuffer *)sampleBuffer
|
||||||
@ -268,7 +267,6 @@ static GstPushSrcClass * parent_class;
|
|||||||
|
|
||||||
duration = gst_util_uint64_scale (GST_SECOND, DEVICE_FPS_D, DEVICE_FPS_N);
|
duration = gst_util_uint64_scale (GST_SECOND, DEVICE_FPS_D, DEVICE_FPS_N);
|
||||||
offset = 0;
|
offset = 0;
|
||||||
prev_ts = GST_CLOCK_TIME_NONE;
|
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
@ -372,9 +370,6 @@ static GstPushSrcClass * parent_class;
|
|||||||
|
|
||||||
- (GstFlowReturn)create:(GstBuffer **)buf
|
- (GstFlowReturn)create:(GstBuffer **)buf
|
||||||
{
|
{
|
||||||
*buf = NULL;
|
|
||||||
|
|
||||||
do {
|
|
||||||
CVPixelBufferRef frame;
|
CVPixelBufferRef frame;
|
||||||
|
|
||||||
[queueLock lockWhenCondition:HAS_FRAME_OR_STOP_REQUEST];
|
[queueLock lockWhenCondition:HAS_FRAME_OR_STOP_REQUEST];
|
||||||
@ -388,8 +383,6 @@ static GstPushSrcClass * parent_class;
|
|||||||
[queueLock unlockWithCondition:
|
[queueLock unlockWithCondition:
|
||||||
([queue count] == 0) ? NO_FRAMES : HAS_FRAME_OR_STOP_REQUEST];
|
([queue count] == 0) ? NO_FRAMES : HAS_FRAME_OR_STOP_REQUEST];
|
||||||
|
|
||||||
if (*buf != NULL)
|
|
||||||
gst_buffer_unref (*buf);
|
|
||||||
*buf = gst_buffer_new_and_alloc (
|
*buf = gst_buffer_new_and_alloc (
|
||||||
CVPixelBufferGetBytesPerRow (frame) * CVPixelBufferGetHeight (frame));
|
CVPixelBufferGetBytesPerRow (frame) * CVPixelBufferGetHeight (frame));
|
||||||
CVPixelBufferLockBaseAddress (frame, 0);
|
CVPixelBufferLockBaseAddress (frame, 0);
|
||||||
@ -397,12 +390,13 @@ static GstPushSrcClass * parent_class;
|
|||||||
GST_BUFFER_SIZE (*buf));
|
GST_BUFFER_SIZE (*buf));
|
||||||
CVPixelBufferUnlockBaseAddress (frame, 0);
|
CVPixelBufferUnlockBaseAddress (frame, 0);
|
||||||
CVBufferRelease (frame);
|
CVBufferRelease (frame);
|
||||||
} while (![self timestampBuffer:*buf]);
|
|
||||||
|
[self timestampBuffer:*buf];
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)timestampBuffer:(GstBuffer *)buf
|
- (void)timestampBuffer:(GstBuffer *)buf
|
||||||
{
|
{
|
||||||
GstClock *clock;
|
GstClock *clock;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
@ -418,8 +412,6 @@ static GstPushSrcClass * parent_class;
|
|||||||
GST_OBJECT_UNLOCK (element);
|
GST_OBJECT_UNLOCK (element);
|
||||||
|
|
||||||
if (clock != NULL) {
|
if (clock != NULL) {
|
||||||
|
|
||||||
/* The time according to the current clock */
|
|
||||||
timestamp = gst_clock_get_time (clock) - timestamp;
|
timestamp = gst_clock_get_time (clock) - timestamp;
|
||||||
if (timestamp > duration)
|
if (timestamp > duration)
|
||||||
timestamp -= duration;
|
timestamp -= duration;
|
||||||
@ -428,55 +420,12 @@ static GstPushSrcClass * parent_class;
|
|||||||
|
|
||||||
gst_object_unref (clock);
|
gst_object_unref (clock);
|
||||||
clock = NULL;
|
clock = NULL;
|
||||||
|
|
||||||
/* Unless it's the first frame, align the current timestamp on a multiple
|
|
||||||
* of duration since the previous */
|
|
||||||
if (GST_CLOCK_TIME_IS_VALID (prev_ts)) {
|
|
||||||
GstClockTime delta;
|
|
||||||
guint delta_remainder, delta_offset;
|
|
||||||
|
|
||||||
if (timestamp < prev_ts) {
|
|
||||||
GST_DEBUG_OBJECT (element, "clock is ticking backwards");
|
|
||||||
return NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Round to a duration boundary */
|
GST_BUFFER_OFFSET (buf) = offset++;
|
||||||
delta = timestamp - prev_ts;
|
|
||||||
delta_remainder = delta % duration;
|
|
||||||
|
|
||||||
if (delta_remainder < duration / 3)
|
|
||||||
timestamp -= delta_remainder;
|
|
||||||
else
|
|
||||||
timestamp += duration - delta_remainder;
|
|
||||||
|
|
||||||
/* How many frames are we off then? */
|
|
||||||
delta = timestamp - prev_ts;
|
|
||||||
delta_offset = delta / duration;
|
|
||||||
|
|
||||||
if (delta_offset == 1) /* perfect */
|
|
||||||
GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
|
|
||||||
else if (delta_offset > 1) {
|
|
||||||
guint lost = delta_offset - 1;
|
|
||||||
GST_DEBUG_OBJECT (element, "lost %d frame%s, setting discont flag",
|
|
||||||
lost, (lost > 1) ? "s" : "");
|
|
||||||
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
|
|
||||||
} else if (delta_offset == 0) { /* overproduction, skip this frame */
|
|
||||||
GST_DEBUG_OBJECT (element, "skipping frame");
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += delta_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_ts = timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BUFFER_OFFSET (buf) = offset;
|
|
||||||
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf) + 1;
|
GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET (buf) + 1;
|
||||||
GST_BUFFER_TIMESTAMP (buf) = timestamp;
|
GST_BUFFER_TIMESTAMP (buf) = timestamp;
|
||||||
GST_BUFFER_DURATION (buf) = duration;
|
GST_BUFFER_DURATION (buf) = duration;
|
||||||
|
|
||||||
return YES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user