blob: 8b8e7ccb4b060021fcb5a0577dd0af04752d2148 [file] [log] [blame]
//
// DecodedFrame.m
// DecoderWrapper
//
// Created by Mike Montalbo on 6/4/12.
// Copyright (c) 2012 Dropcam. All rights reserved.
//
#import "DecodedFrame.h"
#import "NLCommonLoggingNVP.h"
static const CGFloat kDCSceneChangeThreshold = 100.0;
static const NSInteger kDCSubsampleRatio = 500;
@implementation DecodedFrame
+ (DecodedFrame *)decodedFrameWithWidth:(NSUInteger)width
height:(NSUInteger)height
imageBuffer:(CVImageBufferRef)imageBuffer
timestamp:(int64_t)pts {
return [[DecodedFrame alloc] initWithWidth:width
height:height
imageBuffer:imageBuffer
timestamp:pts];
}
- (id)initWithWidth:(NSUInteger)width
height:(NSUInteger)height
yPlane:(NSData *)yPlane
uPlane:(NSData *)uPlane
vPlane:(NSData *)vPlane
timestamp:(int64_t)pts {
if((self = [super init])) {
_width = width;
_height = height;
_yPlane = yPlane;
_uPlane = uPlane;
_vPlane = vPlane;
_PTS = pts;
}
return self;
}
- (id)initWithWidth:(NSUInteger)width
height:(NSUInteger)height
imageBuffer:(CVImageBufferRef)imageBuffer
timestamp:(int64_t)pts {
if((self = [super init])) {
_width = width;
_height = height;
_imageBuffer = imageBuffer;
CVBufferRetain(_imageBuffer);
_PTS = pts;
}
return self;
}
- (NSData *)sceneChangeData {
// only the Y'UV planes version of DecodedFrame is used, it seems.
// we'll just use the luma (Y') plane.
unsigned char *lumaBytes;
size_t lumaLength;
if (self.imageBuffer) {
CVPixelBufferLockBaseAddress(self.imageBuffer, 0);
lumaBytes = (unsigned char *)CVPixelBufferGetBaseAddress(self.imageBuffer);
lumaLength = CVPixelBufferGetDataSize(self.imageBuffer);
}
else {
lumaBytes = (unsigned char *)self.yPlane.bytes;
lumaLength = self.yPlane.length;
}
NSMutableData *data = [NSMutableData dataWithLength:lumaLength / kDCSubsampleRatio];
unsigned char *dataBytes = (unsigned char *)[data mutableBytes];
float sum = 0;
for(int i = 0; i < data.length; i++) {
dataBytes[i] = lumaBytes[i * kDCSubsampleRatio];
sum += dataBytes[i];
}
if (self.imageBuffer) {
CVPixelBufferUnlockBaseAddress(self.imageBuffer, 0);
}
return [NSData dataWithData:data];
}
+ (BOOL)isSceneChangeFromData:(NSData *)data1 toData:(NSData *)data2 {
if((data1.length) != (data2.length))
return NO;
unsigned char *bytes1 = (unsigned char *)[data1 bytes];
unsigned char *bytes2 = (unsigned char *)[data2 bytes];
float diffSum = 0;
for(int i = 0; i < data1.length; i++) {
int diff = bytes1[i]-bytes2[i];
diffSum += diff * diff;
}
BOOL isSceneChange = ((diffSum / data1.length) > kDCSceneChangeThreshold);
if(isSceneChange)
NLLogNVPInfo(@"scenechange detected, diff = %f", (diffSum / data1.length));
return isSceneChange;
}
- (void)dealloc {
CVBufferRelease(_imageBuffer);
}
@end