Skip to content
Permalink
master
Switch branches/tags
Go to file
 
 
Cannot retrieve contributors at this time
278 lines (228 sloc) 6.35 KB
/*
* @file h264-stream.c
* @author Akagi201
* @date 2015/02/02
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "h264-nalu.h"
#include "h264-stream.h"
#include "util.h"
#include "lwlog/lwlog.h"
void print_byte(unsigned char c) {
char s[9] = {0};
int i = 0;
for (i = 7; i >= 0; --i) {
s[7 - i] = BITAT(c, i) ? '1' : '0';
}
s[8] = '\0';
printf("%s = %d\n", s, c);
return;
}
uint32_t h264_next_bits(h264_stream_t *s, int n) {
if (0 == n % 8) {
return h264_stream_peek_bytes(s, n / 8);
}
return h264_stream_peek_bits(s, n);
}
uint32_t h264_u(h264_stream_t *s, uint32_t n) {
//if (n % 8 == 0) {
// return h264_stream_read_bytes(s, n / 8);
//}
return h264_stream_read_bits(s, n);
}
void h264_f(h264_stream_t *s, uint32_t n, uint32_t pattern) {
uint32_t val = h264_u(s, n);
if (val != pattern) {
lwlog_err("h264_f Error: fixed-pattern doesn't match. \nexpected: %x \nactual: %x \n", pattern, (unsigned int) val);
exit(0);
}
}
h264_nalu_t *h264_byte_stream_get_nalu(h264_stream_t *s) {
h264_nalu_t *nalu = NULL;
if ((NULL == s) || (h264_stream_bytes_remaining(s) <= 0)) {
return NULL;
}
while (h264_next_bits(s, 24) != 0x000001 &&
h264_next_bits(s, 32) != 0x00000001) {
h264_f(s, 8, 0x00); // leading_zero_8bits
}
if (h264_next_bits(s, 24) != 0x000001) {
h264_f(s, 8, 0x00); // zero_byte
}
if (h264_stream_bytes_remaining(s) > 0) {
//h264_u(s, 24);
h264_f(s, 24, 0x000001); // start_code_prefix_one_3bytes
nalu = h264_nal_unit(s);
}
while (h264_more_data_in_byte_stream(s) &&
h264_next_bits(s, 24) != 0x000001 &&
h264_next_bits(s, 36) != 0x00000001) {
h264_f(s, 8, 0x00); // trailing_zero_8bits
}
return nu;
}
static uint8_t h264_exp_golomb_bits[256] = {
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0,
};
h264_stream_t *h264_stream_alloc(void) {
h264_stream_t *s = NULL;
s = malloc(sizeof(h264_stream_t));
return s;
}
int h264_stream_init(h264_stream_t *s, uint8_t *data, uint32_t size) {
if (NULL == s) {
lwlog_err("NULL == s");
return -1;
}
s->data = data;
s->size = size;
s->bit_pos = 7;
s->byte_pos = 0;
return 0;
}
h264_stream_t *h264_stream_from_file(char *path) {
FILE *fp = NULL;
long file_size = 0;
uint8_t *buffer = NULL;
size_t result = 0;
h264_stream_t *s = NULL;
fp = fopen(path, "rb");
if (NULL == fp) {
lwlog_err("NULL == fp");
return NULL;
}
fseek(fp, 0, SEEK_END);
file_size = ftell(fp);
rewind(fp);
buffer = (uint8_t *) malloc((size_t) file_size);
assert(buffer);
result = fread(buffer, 1, (size_t) file_size, fp);
assert(result == file_size);
fclose(fp);
s = h264_stream_alloc();
(void) h264_stream_init(s, buffer, (uint32_t) file_size);
return s;
}
void h264_stream_free(h264_stream_t *s) {
if (NULL != s->data) {
free(s->data);
}
s->size = 0;
s->bit_pos = 7;
s->byte_pos = 0;
return;
}
/*
* @brief read n bits from stream s
*/
uint32_t h264_stream_read_bits(h264_stream_t *s, uint32_t n) {
int i = 0;
uint32_t ret = 0;
uint8_t b = 0;
if ((NULL == s) || (0 == n)) {
lwlog_err("h264_stream_read_bits param error");
return 0;
}
for (i = 0; i < n; ++i) {
if (h264_stream_bits_remaining(s) == 0) {
ret <<= n - i - 1;
}
b = s->data[s->byte_pos];
if (n - i <= 32) {
ret = ret << 1 | BITAT(b, s->bit_pos);
}
if (s->bit_pos == 0) {
s->bit_pos = 7;
++s->byte_pos;
} else {
--s->bit_pos;
}
}
return ret;
}
/*
* @brief peek n bits from stream s
*/
uint32_t h264_stream_peek_bits(h264_stream_t *s, uint32_t n) {
uint32_t ret = 0;
int prev_bit_pos = 0;
int prev_byte_pos = 0;
if ((NULL == s) || (0 == n)) {
lwlog_err("h264_stream_peek_bits param error");
return 0;
}
prev_bit_pos = s->bit_pos;
prev_byte_pos = s->byte_pos;
ret = h264_stream_read_bits(s, n);
s->bit_pos = prev_bit_pos;
s->byte_pos = prev_byte_pos;
return ret;
}
/*
* @brief read n bytes from stream s
*/
uint32_t h264_stream_read_bytes(h264_stream_t *s, uint32_t n) {
uint32_t ret = 0;
int i = 0;
if ((NULL == s) || (0 == n)) {
lwlog_err("h264_stream_read_bytes param error");
return 0;
}
for (i = 0; i < n; ++i) {
if (h264_stream_bytes_remaining(s) == 0) {
ret <<= (n - i - 1) * 8;
break;
}
if (n - i <= 4) {
ret = ret << 8 | s->data[s->byte_pos];
}
++s->byte_pos;
}
return ret;
}
/*
* @brief peek n bytes from stream s
*/
uint32_t h264_stream_peek_bytes(h264_stream_t *s, uint32_t n) {
uint32_t ret = 0;
int prev_byte_pos = 0;
if ((NULL == s) || (0 == n)) {
lwlog_err("h264_stream_peek_bytes param error");
return 0;
}
prev_byte_pos = s->byte_pos;
ret = h264_stream_read_bytes(s, n);
s->byte_pos = prev_byte_pos;
return ret;
}
int h264_stream_bits_remaining(h264_stream_t *s) {
if (NULL == s) {
lwlog_err("NULL == s");
return 0;
}
return (s->size - s->byte_pos) * 8 + s->bit_pos - 1;
}
int h264_stream_bytes_remaining(h264_stream_t *s) {
if (NULL == s) {
lwlog_err("NULL == s");
return 0;
}
return s->size - s->byte_pos - 1;
}