blob: 5181099e9626eb409e307f817599598e4e12fc52 [file] [log] [blame] [edit]
//
// H264.m
// Dropcam
//
// Created by Loren Kirkby on 12/18/09.
// Copyright 2009 Dropcam. All rights reserved.
//
#import "H264.h"
uint8_t get_h264_nalu_type(NSData *packet)
{
if ([packet length] < 1)
return -1;
uint8_t header[1] = {0};
[packet getBytes:header length:sizeof(header)];
uint8_t nal_unit_type = (header[0] & 0x1F);
return nal_unit_type;
}
BOOL isStartPacket(NSData *packet)
{
if ([packet length] < 1)
return NO;
uint8_t header[1] = {0};
[packet getBytes:header length:sizeof(header)];
uint8_t nal_unit_type = (header[0] & 0x1F);
return nal_unit_type == 5 || nal_unit_type == 7 || nal_unit_type == 8;
}
static BOOL readBit(NSData *data, int bitpos)
{
uint8_t byte = ((uint8_t*)data.bytes)[bitpos / 8];
int shift = 7 - (bitpos % 8);
uint8_t mask = byte & (1 << shift);
return mask >> shift;
}
static uint32_t readExpGolomb(NSData *data, int *bitpos)
{
// Section 9.1
int leadingZeroBits = -1;
for (int b = 0; !b; leadingZeroBits++) {
b = readBit(data, (*bitpos)++);
}
uint32_t suffix = 0;
for (int i = 1; i <= leadingZeroBits; i++) {
suffix |= readBit(data, (*bitpos)++) << (leadingZeroBits - i);
}
uint32_t pow2 = (1 << leadingZeroBits);
return pow2 - 1 + suffix;
}
H264SliceType getH264SliceType(NSData *packet)
{
if ([packet length] < 2)
return -1;
// Section 7.2
uint8_t naluType = get_h264_nalu_type(packet);
if (naluType != H264_NAL_SLICE_TYPE && naluType != H264_NAL_IDR_TYPE) {
return -1;
}
// Section 7.3
int bitpos = 8;
uint32_t first_mb = readExpGolomb(packet, &bitpos); (void)first_mb;
uint32_t slice_type = readExpGolomb(packet, &bitpos);
return slice_type;
}