mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
Merge pull request #25 from lfasnacht/memory_bitstream
Changed bitstream handling to allow in-memory bitstream.
This commit is contained in:
commit
04f09a2bc8
|
@ -28,6 +28,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
//for hton
|
//for hton
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Winsock2.h>
|
#include <Winsock2.h>
|
||||||
|
@ -113,23 +114,103 @@ void free_exp_golomb()
|
||||||
/**
|
/**
|
||||||
* \brief Create and initialize a new bitstream
|
* \brief Create and initialize a new bitstream
|
||||||
*/
|
*/
|
||||||
bitstream *create_bitstream()
|
bitstream *create_bitstream(const bitstream_type type)
|
||||||
{
|
{
|
||||||
bitstream *stream = malloc(sizeof(bitstream));
|
bitstream *stream = NULL;
|
||||||
if (!stream) {
|
|
||||||
|
if (type == BITSTREAM_TYPE_MEMORY) {
|
||||||
|
bitstream_mem *stream_mem = malloc(sizeof(bitstream_mem));
|
||||||
|
if (!stream_mem) {
|
||||||
fprintf(stderr, "Failed to allocate the bitstream object!\n");
|
fprintf(stderr, "Failed to allocate the bitstream object!\n");
|
||||||
return stream;
|
return NULL;
|
||||||
|
}
|
||||||
|
stream_mem->allocated_length = 0;
|
||||||
|
stream_mem->output_data = NULL;
|
||||||
|
stream_mem->output_length = 0;
|
||||||
|
stream = (bitstream*) stream_mem;
|
||||||
|
} else if (type == BITSTREAM_TYPE_FILE) {
|
||||||
|
bitstream_file *stream_file = malloc(sizeof(bitstream_file));
|
||||||
|
if (!stream_file) {
|
||||||
|
fprintf(stderr, "Failed to allocate the bitstream object!\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
//FIXME: it would make sense to avoid constructing an incomplete object
|
||||||
|
stream_file->output = NULL;
|
||||||
|
stream = (bitstream*) stream_file;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unknown type for bitstream!\n");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize buffer-related values
|
// Initialize buffer-related values
|
||||||
stream->data = 0;
|
stream->data = 0;
|
||||||
stream->cur_bit = 0;
|
stream->cur_bit = 0;
|
||||||
stream->zerocount = 0;
|
stream->zerocount = 0;
|
||||||
|
stream->type = type;
|
||||||
|
|
||||||
|
|
||||||
// Return the created bitstream
|
// Return the created bitstream
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Free a bitstream
|
||||||
|
*/
|
||||||
|
void free_bitstream(bitstream* stream)
|
||||||
|
{
|
||||||
|
if (stream->type == BITSTREAM_TYPE_MEMORY) {
|
||||||
|
bitstream_mem *stream_mem = (bitstream_mem*) stream;
|
||||||
|
FREE_POINTER(stream_mem->output_data);
|
||||||
|
} else if (stream->type == BITSTREAM_TYPE_FILE) {
|
||||||
|
bitstream_file *stream_file = (bitstream_file*) stream;
|
||||||
|
//FIXME: if we fix create_bitstream, we would maybe have to do something here
|
||||||
|
stream_file->output = NULL;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unknown type for bitstream!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FREE_POINTER(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Write a byte to bitstream
|
||||||
|
* \param stream_abstract pointer bitstream to put the data
|
||||||
|
* \param byte byte to write
|
||||||
|
* \return 1 on success, 0 on failure
|
||||||
|
*/
|
||||||
|
static int bitstream_writebyte(bitstream *stream_abstract, uint8_t byte) {
|
||||||
|
if (stream_abstract->type == BITSTREAM_TYPE_FILE) {
|
||||||
|
bitstream_file *stream = (bitstream_file*) stream_abstract;
|
||||||
|
if (fwrite(&byte, 1, 1, stream->output) != 1) {
|
||||||
|
fprintf(stderr, "Could not write byte to bitstream_file object.");
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (stream_abstract->type == BITSTREAM_TYPE_MEMORY) {
|
||||||
|
bitstream_mem *stream = (bitstream_mem*) stream_abstract;
|
||||||
|
if (stream->allocated_length==stream->output_length) {
|
||||||
|
//Need to reallocate
|
||||||
|
uint32_t new_size = stream->allocated_length + BITSTREAM_MEMORY_CHUNK_SIZE;
|
||||||
|
uint8_t* new_data = realloc(stream->output_data, new_size);
|
||||||
|
if (!new_data) {
|
||||||
|
fprintf(stderr, "Failed to allocate memory for bitstream_mem object");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
stream->output_data = new_data;
|
||||||
|
stream->allocated_length = new_size;
|
||||||
|
}
|
||||||
|
//Write byte
|
||||||
|
stream->output_data[stream->output_length++] = byte;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unknown stream type %d.", stream_abstract->type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Put bits to bitstream
|
* \brief Put bits to bitstream
|
||||||
* \param stream pointer bitstream to put the data
|
* \param stream pointer bitstream to put the data
|
||||||
|
@ -150,7 +231,7 @@ void bitstream_put(bitstream *stream, uint32_t data, uint8_t bits)
|
||||||
// write byte to output
|
// write byte to output
|
||||||
if (stream->cur_bit==8) {
|
if (stream->cur_bit==8) {
|
||||||
if((stream->zerocount == 2) && (stream->data < 4)) {
|
if((stream->zerocount == 2) && (stream->data < 4)) {
|
||||||
fwrite(&emulation_prevention_three_byte, 1, 1, stream->output);
|
bitstream_writebyte(stream, emulation_prevention_three_byte);
|
||||||
stream->zerocount = 0;
|
stream->zerocount = 0;
|
||||||
}
|
}
|
||||||
if(stream->data == 0) {
|
if(stream->data == 0) {
|
||||||
|
@ -158,7 +239,7 @@ void bitstream_put(bitstream *stream, uint32_t data, uint8_t bits)
|
||||||
} else {
|
} else {
|
||||||
stream->zerocount = 0;
|
stream->zerocount = 0;
|
||||||
}
|
}
|
||||||
fwrite(&stream->data, 1, 1, stream->output);
|
bitstream_writebyte(stream, stream->data);
|
||||||
stream->cur_bit = 0;
|
stream->cur_bit = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,15 +26,32 @@
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
|
typedef enum {BITSTREAM_TYPE_FILE, BITSTREAM_TYPE_MEMORY} bitstream_type;
|
||||||
|
|
||||||
|
#define BASE_BITSTREAM uint8_t data; uint8_t cur_bit; uint8_t zerocount; bitstream_type type;
|
||||||
|
|
||||||
|
//Size of the allocation for a memory bitstream in bytes
|
||||||
|
#define BITSTREAM_MEMORY_CHUNK_SIZE 4096
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t data;
|
BASE_BITSTREAM
|
||||||
uint8_t cur_bit;
|
|
||||||
uint8_t zerocount;
|
|
||||||
FILE* output;
|
|
||||||
} bitstream;
|
} bitstream;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
BASE_BITSTREAM
|
||||||
|
FILE* output;
|
||||||
|
} bitstream_file;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
BASE_BITSTREAM
|
||||||
|
uint8_t* output_data;
|
||||||
|
uint32_t output_length;
|
||||||
|
uint32_t allocated_length;
|
||||||
|
} bitstream_mem;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint8_t len;
|
uint8_t len;
|
||||||
|
@ -46,6 +63,7 @@ extern bit_table *g_exp_table;
|
||||||
int floor_log2(unsigned int n);
|
int floor_log2(unsigned int n);
|
||||||
|
|
||||||
bitstream *create_bitstream();
|
bitstream *create_bitstream();
|
||||||
|
void free_bitstream(bitstream* stream);
|
||||||
void bitstream_put(bitstream* stream, uint32_t data, uint8_t bits);
|
void bitstream_put(bitstream* stream, uint32_t data, uint8_t bits);
|
||||||
|
|
||||||
/* Use macros to force inlining */
|
/* Use macros to force inlining */
|
||||||
|
|
|
@ -221,7 +221,7 @@ int main(int argc, char *argv[])
|
||||||
// Set output file
|
// Set output file
|
||||||
|
|
||||||
encoder->output = output;
|
encoder->output = output;
|
||||||
encoder->stream->output = output;
|
((bitstream_file*) encoder->stream)->output = output;
|
||||||
// input init (TODO: read from commandline / config)
|
// input init (TODO: read from commandline / config)
|
||||||
encoder->bitdepth = 8;
|
encoder->bitdepth = 8;
|
||||||
encoder->frame = 0;
|
encoder->frame = 0;
|
||||||
|
@ -401,7 +401,7 @@ int main(int argc, char *argv[])
|
||||||
picture_list_destroy(encoder->ref);
|
picture_list_destroy(encoder->ref);
|
||||||
picture_destroy(encoder->in.cur_pic);
|
picture_destroy(encoder->in.cur_pic);
|
||||||
FREE_POINTER(encoder->in.cur_pic);
|
FREE_POINTER(encoder->in.cur_pic);
|
||||||
FREE_POINTER(encoder->stream);
|
free_bitstream(encoder->stream);
|
||||||
free(encoder);
|
free(encoder);
|
||||||
free_tables();
|
free_tables();
|
||||||
free_exp_golomb();
|
free_exp_golomb();
|
||||||
|
|
|
@ -283,7 +283,7 @@ encoder_control *init_encoder_control(config *cfg)
|
||||||
enc_c->rdo = 1;
|
enc_c->rdo = 1;
|
||||||
|
|
||||||
// Allocate the bitstream struct
|
// Allocate the bitstream struct
|
||||||
stream = create_bitstream();
|
stream = create_bitstream(BITSTREAM_TYPE_FILE);
|
||||||
if (!stream) {
|
if (!stream) {
|
||||||
fprintf(stderr, "Failed to allocate the bitstream object!\n");
|
fprintf(stderr, "Failed to allocate the bitstream object!\n");
|
||||||
goto init_failure;
|
goto init_failure;
|
||||||
|
|
Loading…
Reference in a new issue