mirror of
https://github.com/ultravideo/uvg266.git
synced 2024-11-27 19:24:06 +00:00
Output bitstream through API.
- Use the existing bitstream_t type to give access to the bitstream. We can extend it later to make it a linked list like I was planning to do with the payload type. - The main encoder now also stores the bitstream in memory.
This commit is contained in:
parent
df50a0dae6
commit
fc58748ae8
|
@ -53,7 +53,7 @@ typedef struct
|
|||
uint32_t allocated_length;
|
||||
} bitstream_mem_t;
|
||||
|
||||
typedef union
|
||||
typedef union bitstream_t
|
||||
{
|
||||
bitstream_base_t base;
|
||||
bitstream_file_t file;
|
||||
|
|
|
@ -117,13 +117,19 @@ int main(int argc, char *argv[])
|
|||
} else {
|
||||
// Otherwise we try to open the output file
|
||||
output = fopen(cfg->output, "wb");
|
||||
// Check that output was opened correctly
|
||||
if (output == NULL) {
|
||||
fprintf(stderr, "Could not open output file, shutting down!\n");
|
||||
goto exit_failure;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that output was opened correctly
|
||||
if (output == NULL) {
|
||||
fprintf(stderr, "Could not open output file, shutting down!\n");
|
||||
goto exit_failure;
|
||||
bitstream_t output_stream;
|
||||
if (!bitstream_init(&output_stream, BITSTREAM_TYPE_FILE)) {
|
||||
fprintf(stderr, "Could not initialize stream!\n");
|
||||
return 0;
|
||||
}
|
||||
output_stream.file.output = output;
|
||||
|
||||
if (cfg->debug != NULL) {
|
||||
recout = fopen(cfg->debug, "wb");
|
||||
|
@ -147,11 +153,6 @@ int main(int argc, char *argv[])
|
|||
goto exit_failure;
|
||||
}
|
||||
|
||||
|
||||
for (unsigned i = 0; i <= cfg->owf; ++i) {
|
||||
enc->states[i].stream.file.output = output;
|
||||
}
|
||||
|
||||
encoder_control_t *encoder = enc->control;
|
||||
|
||||
fprintf(stderr, "Input: %s, output: %s\n", cfg->input, cfg->output);
|
||||
|
@ -223,7 +224,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
|
||||
image_t *img_out = NULL;
|
||||
api->encoder_encode(enc, img_in, &img_out, NULL);
|
||||
api->encoder_encode(enc, img_in, &img_out, &output_stream);
|
||||
|
||||
if (img_out != NULL) {
|
||||
state = &enc->states[enc->cur_state_num];
|
||||
|
@ -247,9 +248,8 @@ int main(int argc, char *argv[])
|
|||
int first_enc = current_encoder_state;
|
||||
do {
|
||||
double frame_psnr[3] = { 0.0, 0.0, 0.0 };
|
||||
encoder_state_t *state = &enc->states[current_encoder_state];
|
||||
image_t *img_out = NULL;
|
||||
api->encoder_encode(enc, NULL, &img_out, NULL);
|
||||
api->encoder_encode(enc, NULL, &img_out, &output_stream);
|
||||
|
||||
if (img_out != NULL) {
|
||||
encoder_state_t *state = &enc->states[current_encoder_state];
|
||||
|
@ -292,6 +292,8 @@ int main(int argc, char *argv[])
|
|||
fprintf(stderr, " FPS: %.2f\n", ((double)frames_done)/wall_time);
|
||||
}
|
||||
|
||||
bitstream_finalize(&output_stream);
|
||||
|
||||
fclose(input);
|
||||
fclose(output);
|
||||
if(recout != NULL) fclose(recout);
|
||||
|
|
|
@ -817,9 +817,6 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state) {
|
|||
state->global->cur_gop_bits_coded = 0;
|
||||
}
|
||||
state->global->cur_gop_bits_coded += newpos - curpos;
|
||||
|
||||
// Flush the output in case someone is reading the file on the other end.
|
||||
fflush(state->stream.file.output);
|
||||
}
|
||||
|
||||
void encoder_state_write_bitstream_leaf(encoder_state_t * const state) {
|
||||
|
|
|
@ -322,20 +322,9 @@ int encoder_state_init(encoder_state_t * const child_state, encoder_state_t * co
|
|||
if (!child_state->wfrow) child_state->wfrow = parent_state->wfrow;
|
||||
}
|
||||
|
||||
//Allocate bitstream
|
||||
if (child_state->type == ENCODER_STATE_TYPE_MAIN) {
|
||||
//Main encoder outputs to file
|
||||
if (!bitstream_init(&child_state->stream, BITSTREAM_TYPE_FILE)) {
|
||||
fprintf(stderr, "Could not initialize stream!\n");
|
||||
return 0;
|
||||
}
|
||||
child_state->stream.file.output = NULL;
|
||||
} else {
|
||||
//Other encoders use a memory bitstream
|
||||
if (!bitstream_init(&child_state->stream, BITSTREAM_TYPE_MEMORY)) {
|
||||
fprintf(stderr, "Could not initialize stream!\n");
|
||||
return 0;
|
||||
}
|
||||
if (!bitstream_init(&child_state->stream, BITSTREAM_TYPE_MEMORY)) {
|
||||
fprintf(stderr, "Could not initialize stream!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set CABAC output bitstream
|
||||
|
|
|
@ -786,7 +786,8 @@ static void encoder_state_new_frame(encoder_state_t * const state) {
|
|||
state->global->cur_lambda_cost = lambda;
|
||||
state->global->cur_lambda_cost_sqrt = sqrt(lambda);
|
||||
|
||||
} else {
|
||||
}
|
||||
if (state->stream.base.type == BITSTREAM_TYPE_MEMORY) {
|
||||
//Clear the bitstream if it's not the main encoder
|
||||
bitstream_clear(&state->stream);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "strategyselector.h"
|
||||
#include "encoderstate.h"
|
||||
#include "checkpoint.h"
|
||||
#include "bitstream.h"
|
||||
|
||||
|
||||
static void kvazaar_close(kvz_encoder *encoder)
|
||||
|
@ -106,7 +107,7 @@ kvazaar_open_failure:
|
|||
}
|
||||
|
||||
|
||||
static int kvazaar_encode(kvz_encoder *enc, kvz_picture *img_in, kvz_picture **img_out, kvz_payload **payload)
|
||||
static int kvazaar_encode(kvz_encoder *enc, kvz_picture *img_in, kvz_picture **img_out, kvz_payload *payload)
|
||||
{
|
||||
// If img_in is NULL, just return the next unfinished frame.
|
||||
if (img_in != NULL) {
|
||||
|
@ -126,6 +127,14 @@ static int kvazaar_encode(kvz_encoder *enc, kvz_picture *img_in, kvz_picture **i
|
|||
|
||||
if (enc->frames_started >= enc->num_encoder_states && !state->stats_done) {
|
||||
threadqueue_waitfor(enc->control->threadqueue, state->tqj_bitstream_written);
|
||||
|
||||
bitstream_append(payload, &state->stream);
|
||||
|
||||
// Flush the output in case someone is reading the file on the other end.
|
||||
if (payload->base.type == BITSTREAM_TYPE_FILE) {
|
||||
fflush(payload->file.output);
|
||||
}
|
||||
|
||||
*img_out = image_make_subimage(state->tile->frame->rec, 0, 0, state->tile->frame->width, state->tile->frame->height);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ extern "C" {
|
|||
|
||||
typedef struct config_t kvz_cfg;
|
||||
typedef struct encoder_state_t encoder_state_t;
|
||||
typedef struct kvz_payload kvz_payload;
|
||||
typedef union bitstream_t kvz_payload;
|
||||
typedef struct encoder_control_t encoder_control_t;
|
||||
typedef struct image_t kvz_picture;
|
||||
|
||||
|
@ -49,17 +49,6 @@ typedef uint16_t pixel_t;
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* A payload unit containing at most a single frame.
|
||||
* If next is not NULL, the bytestream continues in that payload unit.
|
||||
*/
|
||||
typedef struct kvz_payload {
|
||||
uint32_t type;
|
||||
uint32_t size_bytes;
|
||||
uint8_t *payload;
|
||||
kvz_payload *next;
|
||||
} kvz_payload;
|
||||
|
||||
/**
|
||||
* \brief Struct which contains all picture data
|
||||
*/
|
||||
|
@ -113,7 +102,7 @@ typedef struct kvz_api {
|
|||
// \param pic_out Picture containing the reconstructed data.
|
||||
// \param nals_out The first NAL containing bitstream generated, or NULL.
|
||||
// \return 1 on success, negative on error.
|
||||
int (*encoder_encode)(kvz_encoder *encoder, kvz_picture *pic_in, kvz_picture **pic_out, kvz_payload **payload);
|
||||
int (*encoder_encode)(kvz_encoder *encoder, kvz_picture *pic_in, kvz_picture **pic_out, kvz_payload *payload);
|
||||
} kvz_api;
|
||||
|
||||
// Append API version to the getters name to prevent linking against incompatible versions.
|
||||
|
|
Loading…
Reference in a new issue