blob: 710002ef4db9ea02d6e753119ca909b32285f2e3 [file]
//
// DCAdaptiveJitterBuffer.m
// NexusVideoPlayer
//
// Created by Frank Huang on 11/18/13.
// Copyright (c) 2013 Dropcam. All rights reserved.
//
#import "DCAdaptiveJitterBuffer.h"
#import "NSCondition+UnlockAfter.h"
#include "AdaptiveJitterBuffer.hpp"
@implementation Packet
@end
@interface DCAdaptiveJitterBuffer ()
@property (nonatomic, assign) AdaptiveJitterBuffer *buffer;
@property (nonatomic, strong) NSCondition *packetCondition;
@end
@implementation DCAdaptiveJitterBuffer
- (id)initWithTimebase:(int)timebase isLive:(BOOL)isLive isWifi:(BOOL)isWifi {
if ((self = [super init])) {
_buffer = new AdaptiveJitterBuffer(timebase, isLive == YES, isWifi == YES);
_packetCondition = [[NSCondition alloc] init];
}
return self;
}
- (void)dealloc {
delete _buffer;
}
- (void)setAutoAdjust:(BOOL)adjust {
[self.packetCondition unlockAfter:^{
_buffer->setAutoAdjust(adjust);
}];
}
- (int64_t)targetDelay {
__block int64_t rval;
[self.packetCondition unlockAfter:^{
rval = _buffer->getTargetDelay();
}];
return rval;
}
- (void)setTargetDelay:(int64_t)delay {
[self.packetCondition unlockAfter:^{
_buffer->setTargetDelay(delay);
}];
}
- (void)addBias:(int64_t)bias {
[self.packetCondition unlockAfter:^{
_buffer->addBias(bias);
}];
}
- (int)numPackets {
__block int rval;
[self.packetCondition unlockAfter:^{
rval = _buffer->getNumPackets();
}];
return rval;
}
- (int64_t)bufferLength {
__block int64_t rval;
[self.packetCondition unlockAfter:^{
rval = _buffer->getBufferLength();
}];
return rval;
}
- (BOOL)fullyBuffered {
__block BOOL rval;
[self.packetCondition unlockAfter:^{
rval = _buffer->getFullyBuffered();
}];
return rval;
}
- (void)addPacket:(Packet*)packet {
[self.packetCondition unlockAfter:^{
JBPacket in_pkt = {
.seq_num = packet.sequenceNumber,
.PTS = packet.PTS,
.span = 0,
// transfer ownership of packet to JB
.payload_data = (__bridge_retained void*)packet
};
_buffer->addPacket(in_pkt);
[self.packetCondition signal];
}];
}
- (void)addSlaveTiming:(int64_t)PTS {
[self.packetCondition unlockAfter:^{
_buffer->addSlaveTiming(PTS);
}];
}
- (int64_t)peekPTS {
__block int64_t rval;
[self.packetCondition unlockAfter:^{
rval = _buffer->peekPTS();
}];
return rval;
}
- (Packet*)nextPacket {
__block Packet *packet = nil;
[self.packetCondition unlockAfter:^{
JBPacket out_pkt;
bool has_pkt = _buffer->nextPacket(out_pkt);
if (!has_pkt) {
return;
}
// Take ownership of packet back from JB
packet = (__bridge_transfer Packet*)out_pkt.payload_data;
}];
return packet;
}
- (BOOL)waitForPacket {
__block BOOL rval = NO;
[self.packetCondition unlockAfter:^{
NSThread *thread = [NSThread currentThread];
while (![thread isCancelled]) {
[self.packetCondition wait];
if (_buffer->getNumPackets() == 0) {
continue;
}
else {
rval = YES;
return;
}
}
}];
return rval;
}
- (void)cancelWaiters {
[self.packetCondition unlockAfter:^{
[self.packetCondition broadcast];
}];
}
- (float)playSpeedForPTS:(int64_t)PTS {
__block float rval;
[self.packetCondition unlockAfter:^{
rval = _buffer->getPlaySpeedForPTS(PTS);
}];
return rval;
}
@end