File cap.: use UG conversion + codec opt

Use UltraGrid covnversion if available instead of swscale. Added codec option
This commit is contained in:
Martin Pulec
2020-08-14 15:11:21 +02:00
parent c9c1afeaf1
commit 9e4b317e8f
3 changed files with 47 additions and 8 deletions

View File

@@ -2138,6 +2138,19 @@ const struct av_to_uv_conversion *get_av_to_uv_conversions() {
return av_to_uv_conversions;
}
av_to_uv_convert_p get_av_to_uv_conversion(int av_codec, codec_t uv_codec) {
for (const struct av_to_uv_conversion *conversions = get_av_to_uv_conversions();
conversions->convert != 0; conversions++) {
if (conversions->av_codec == av_codec &&
conversions->uv_codec == uv_codec) {
return conversions->convert;
}
}
return NULL;
}
#ifdef HAVE_SWSCALE
/**
* Simplified version of this: https://cpp.hotexamples.com/examples/-/-/av_opt_set_int/cpp-av_opt_set_int-function-examples.html

View File

@@ -207,6 +207,7 @@ struct av_to_uv_conversion {
///< not have codec for eg. 4:4:4 UYVY).
};
av_to_uv_convert_p get_av_to_uv_conversion(int av_codec, codec_t uv_codec);
const struct av_to_uv_conversion *get_av_to_uv_conversions(void);
codec_t get_av_to_ug_codec(enum AVCodecID av_codec);

View File

@@ -88,11 +88,15 @@ struct vidcap_state_lavf_decoder {
char *src_filename;
AVFormatContext *fmt_ctx;
AVCodecContext *aud_ctx, *vid_ctx;
struct SwsContext *sws_ctx;
av_to_uv_convert_p conv_uv;
bool failed;
bool loop;
bool new_msg;
bool no_decode;
codec_t convert_to;
bool paused;
bool use_audio;
@@ -118,12 +122,14 @@ struct vidcap_state_lavf_decoder {
static void vidcap_file_show_help() {
color_out(0, "Usage:\n");
color_out(COLOR_OUT_BOLD | COLOR_OUT_RED, "\t-t file:<name>");
color_out(COLOR_OUT_BOLD, "[:loop][:nodecode]\n");
color_out(COLOR_OUT_BOLD, "[:loop][:nodecode][:codec=<c>]\n");
color_out(0, "\t\twhere\n");
color_out(COLOR_OUT_BOLD, "\tloop\n");
color_out(0, "\t\tloop the playback\n");
color_out(COLOR_OUT_BOLD, "\tnodecode\n");
color_out(0, "\t\tdon't decompress the video (may not work because required data for correct decompess are in container or UG doesn't recognize the codec)\n");
color_out(COLOR_OUT_BOLD, "\tcodec\n");
color_out(0, "\t\tcodec to decode to\n");
}
static void vidcap_file_common_cleanup(struct vidcap_state_lavf_decoder *s) {
@@ -318,8 +324,13 @@ static void *vidcap_file_worker(void *state) {
* this is required since rawvideo expects non aligned data */
int video_dst_linesize[4] = { vc_get_linesize(out->tiles[0].width, out->color_spec) };
uint8_t *dst[4] = { (uint8_t *) out->tiles[0].data };
sws_scale(s->sws_ctx, (const uint8_t * const *) frame->data, frame->linesize, 0,
frame->height, dst, video_dst_linesize);
if (s->conv_uv) {
int rgb_shift[] = {0, 8, 16};
s->conv_uv(out->tiles[0].data, frame, out->tiles[0].width, out->tiles[0].height, video_dst_linesize[0], rgb_shift);
} else {
sws_scale(s->sws_ctx, (const uint8_t * const *) frame->data, frame->linesize, 0,
frame->height, dst, video_dst_linesize);
}
av_frame_free(&frame);
out->callbacks.dispose = vf_free;
}
@@ -359,6 +370,12 @@ static bool vidcap_file_parse_fmt(struct vidcap_state_lavf_decoder *s, const cha
s->no_decode = true;
} else if (strcmp(item, "opportunistic_audio") == 0) {
*opportunistic_audio = true;
} else if (strncmp(item, "codec=", strlen("codec=")) == 0) {
char *codec_name = item + strlen("codec=");
if ((s->convert_to = get_codec_from_name(codec_name)) == VIDEO_CODEC_NONE) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unknown option: %s\n", codec_name);
return false;
}
} else {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unknown option: %s\n", item);
return false;
@@ -428,6 +445,7 @@ static int vidcap_file_init(struct vidcap_params *params, void **state) {
struct vidcap_state_lavf_decoder *s = calloc(1, sizeof (struct vidcap_state_lavf_decoder));
s->audio_stream_idx = -1;
s->video_stream_idx = -1;
s->convert_to = UYVY;
CHECK(pthread_mutex_init(&s->audio_frame_lock, NULL));
CHECK(pthread_mutex_init(&s->lock, NULL));
CHECK(pthread_cond_init(&s->frame_consumed, NULL));
@@ -500,7 +518,7 @@ static int vidcap_file_init(struct vidcap_params *params, void **state) {
s->video_desc.height = st->codecpar->height;
s->video_desc.fps = (double) st->r_frame_rate.num / st->r_frame_rate.den;
s->video_desc.tile_count = 1;
fprintf(stderr, "%d %d\n", s->video_desc.width, s->video_desc.height);
log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Video size: %dx%d\n", s->video_desc.width, s->video_desc.height);
if (s->no_decode) {
s->video_desc.color_spec =
get_av_to_ug_codec(s->fmt_ctx->streams[s->video_stream_idx]->codecpar->codec_id);
@@ -511,16 +529,23 @@ fprintf(stderr, "%d %d\n", s->video_desc.width, s->video_desc.height);
return VIDCAP_INIT_FAIL;
}
} else {
s->video_desc.color_spec = UYVY;
s->video_desc.color_spec = s->convert_to;
s->vid_ctx = vidcap_file_open_dec_ctx(dec, st);
if (!s->vid_ctx) {
vidcap_file_common_cleanup(s);
return VIDCAP_INIT_FAIL;
}
s->sws_ctx = sws_getContext(s->video_desc.width, s->video_desc.height, s->vid_ctx->pix_fmt,
s->video_desc.width, s->video_desc.height, get_ug_to_av_pixfmt(s->video_desc.color_spec),
0, NULL, NULL, NULL);
if ((s->conv_uv = get_av_to_uv_conversion(s->vid_ctx->pix_fmt, s->video_desc.color_spec)) == NULL) {
s->sws_ctx = sws_getContext(s->video_desc.width, s->video_desc.height, s->vid_ctx->pix_fmt,
s->video_desc.width, s->video_desc.height, get_ug_to_av_pixfmt(s->video_desc.color_spec),
0, NULL, NULL, NULL);
if (s->sws_ctx == NULL) {
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Cannot find neither UltraGrid nor swscale conversion!\n");
vidcap_file_common_cleanup(s);
return VIDCAP_INIT_FAIL;
}
}
}
s->video_desc.interlacing = PROGRESSIVE; /// @todo other modes
}