Added transition from LFF to interlaced merged

This commit is contained in:
Martin Pulec
2014-11-12 15:31:45 +01:00
parent 62c936a964
commit 88ee65c66b
3 changed files with 72 additions and 7 deletions

View File

@@ -109,7 +109,7 @@ struct state_video_decoder;
* Interlacing changing function protoype. The function should be able to change buffer
* in place, that is when dst and src are the same.
*/
typedef void (*change_il_t)(char *dst, char *src, int linesize, int height);
typedef void (*change_il_t)(char *dst, char *src, int linesize, int height, void **state);
// prototypes
static bool reconfigure_decoder(struct state_video_decoder *decoder,
@@ -216,6 +216,7 @@ struct state_video_decoder
unsigned int max_substreams; ///< maximal number of expected substreams
change_il_t change_il; ///< function to change interlacing, if needed. Otherwise NULL.
vector<void *> change_il_state;
mutex lock;
@@ -526,7 +527,7 @@ static void *decompress_thread(void *args) {
for(i = 0; i < decoder->frame->tile_count; ++i) {
struct tile *tile = vf_get_tile(decoder->frame, i);
decoder->change_il(tile->data, tile->data, vc_get_linesize(tile->width,
decoder->out_codec), tile->height);
decoder->out_codec), tile->height, &decoder->change_il_state[i]);
}
}
@@ -782,6 +783,11 @@ static void cleanup(struct state_video_decoder *decoder)
free(decoder->line_decoder);
decoder->line_decoder = NULL;
}
for (auto && item : decoder->change_il_state) {
free(item);
}
decoder->change_il_state.resize(0);
}
#define PRINT_STATISTICS fprintf(stderr, "Video decoder statistics: %lu total: %lu displayed / %lu "\
@@ -1039,6 +1045,7 @@ static change_il_t select_il_func(enum interlacing_t in_il, enum interlacing_t *
struct transcode_t { enum interlacing_t in; enum interlacing_t out; change_il_t func; };
struct transcode_t transcode[] = {
{LOWER_FIELD_FIRST, INTERLACED_MERGED, il_lower_to_merged},
{UPPER_FIELD_FIRST, INTERLACED_MERGED, il_upper_to_merged},
{INTERLACED_MERGED, UPPER_FIELD_FIRST, il_merged_to_upper}
};
@@ -1062,6 +1069,8 @@ static change_il_t select_il_func(enum interlacing_t in_il, enum interlacing_t *
}
}
fprintf(stderr, "[Warning] Cannot find transition between incoming and display "
"interlacing modes!\n");
return NULL;
}
@@ -1146,6 +1155,7 @@ static bool reconfigure_decoder(struct state_video_decoder *decoder,
decoder->change_il = select_il_func(desc.interlacing, decoder->disp_supported_il,
decoder->disp_supported_il_cnt, &display_il);
decoder->change_il_state.resize(decoder->max_substreams);
if (!decoder->postprocess || !pp_does_change_tiling_mode) { /* otherwise we need postprocessor mode, which we obtained before */
render_mode = display_mode;

View File

@@ -211,9 +211,62 @@ const char *get_interlacing_suffix(enum interlacing_t interlacing)
return NULL;
}
/* TODO: rewrite following 2 functions in more efficient way */
void il_upper_to_merged(char *dst, char *src, int linesize, int height)
/**
* @todo
* Needs to be more efficient
*/
void il_lower_to_merged(char *dst, char *src, int linesize, int height, void **stored_state)
{
struct il_lower_to_merged_state {
size_t field_len;
char field[];
};
struct il_lower_to_merged_state *last_field = (struct il_lower_to_merged_state *) *stored_state;
int y;
char *tmp = malloc(linesize * height);
char *line1, *line2;
// upper field
line1 = tmp;
int field_len = linesize * (height / 2);
// first check if we have field from last frame
if (last_field == NULL) {
last_field = (struct il_lower_to_merged_state *)
malloc(sizeof(struct il_lower_to_merged_state) + field_len);
last_field->field_len = field_len;
*stored_state = last_field;
// if no, use current one
line2 = src + linesize * ((height + 1) / 2);
} else {
// otherwise use field from last "frame"
line2 = last_field->field;
}
for(y = 0; y < height / 2; y ++) {
memcpy(line1, line2, linesize);
line1 += linesize * 2;
line2 += linesize;
}
// store
assert ((int) last_field->field_len == field_len);
memcpy(last_field->field, src + linesize * ((height + 1) / 2), field_len);
// lower field
line1 = tmp + linesize;
line2 = src;
for(y = 0; y < (height + 1) / 2; y ++) {
memcpy(line1, line2, linesize);
line1 += linesize * 2;
line2 += linesize;
}
memcpy(dst, tmp, linesize * height);
free(tmp);
}
/* TODO: rewrite following 2 functions in more efficient way */
void il_upper_to_merged(char *dst, char *src, int linesize, int height, void **state)
{
UNUSED(state);
int y;
char *tmp = malloc(linesize * height);
char *line1, *line2;
@@ -237,8 +290,9 @@ void il_upper_to_merged(char *dst, char *src, int linesize, int height)
free(tmp);
}
void il_merged_to_upper(char *dst, char *src, int linesize, int height)
void il_merged_to_upper(char *dst, char *src, int linesize, int height, void **state)
{
UNUSED(state);
int y;
char *tmp = malloc(linesize * height);
char *line1, *line2;

View File

@@ -151,15 +151,16 @@ const char *get_interlacing_description(enum interlacing_t interlacing);
*/
const char *get_interlacing_suffix(enum interlacing_t interlacing);
void il_lower_to_merged(char *dst, char *src, int linesize, int height, void **stored_state);
/* these functions transcode one interlacing format to another */
/**
* @brief Converts upper-field-first to interlaced merged.
*/
void il_upper_to_merged(char *dst, char *src, int linesize, int height);
void il_upper_to_merged(char *dst, char *src, int linesize, int height, void **stored_state);
/**
* @brief Converts interlaced merged to upper-field-first.
*/
void il_merged_to_upper(char *dst, char *src, int linesize, int height);
void il_merged_to_upper(char *dst, char *src, int linesize, int height, void **stored_state);
/**
* @brief Computes FPS as a double from packet fields.