56#include <libavcodec/avcodec.h>
57#include <libavcodec/version.h>
58#include <libavformat/avformat.h>
59#include <libavformat/version.h>
60#include <libavutil/avutil.h>
61#include <libswscale/swscale.h>
94#define MAGIC to_fourcc('u', 'g', 'l', 'f')
95#define MOD_NAME "[File cap.] "
149 full ?
"[:opportunistic_audio][:queue=<len>][:threads=<n>[FS]]" :
"");
154 color_printf(
"\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");
159 color_printf(
"\t\tgrab audio if not present but do not fail if not\n");
163 color_printf(
"\t\tnumber of threads (0 is default), 'S' and/or 'F' to use slice/frame threads, use at least one flag\n");
165 color_printf(
"\n(use \":fullhelp\" to see all available options)\n");
181 avcodec_flush_buffers(s->
vid_ctx);
184 avcodec_flush_buffers(s->
aud_ctx);
194 avcodec_free_context(&s->
vid_ctx);
197 avcodec_free_context(&s->
aud_ctx);
200 avformat_close_input(&s->
fmt_ctx);
209 pthread_mutex_destroy(&s->
lock);
220 const int plane_count = av_sample_fmt_is_planar(s->
aud_ctx->sample_fmt)
224 if (av_get_alt_sample_fmt(s->
aud_ctx->sample_fmt, 0) == AV_SAMPLE_FMT_FLT) {
225 for (
int i = 0; i < plane_count; ++i) {
228 }
else if (av_get_alt_sample_fmt(s->
aud_ctx->sample_fmt, 0) == AV_SAMPLE_FMT_DBL) {
237 if (av_sample_fmt_is_planar(s->
aud_ctx->sample_fmt)) {
238 int bps = av_get_bytes_per_sample(s->
aud_ctx->sample_fmt);
239 char tmp[plane_count * bps *
frame->nb_samples];
240 for (
int i = 0; i < plane_count; ++i) {
242 frame->nb_samples * bps, plane_count,
261 for (
int i = 0; i <
frame->nb_samples; ++i) {
263 (
char *)
frame->data[0] +
285 vid_frm_ts * vtb.num / vtb.den +
286 (vid_frm_dur * vtb.num * 3 / vtb.den / 4);
290 AVPacket *pkt, AVFrame *
frame) {
291 int ret = avcodec_send_packet(s->
aud_ctx, pkt);
298 if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
312 while (vid_frm != NULL) {
317 pthread_mutex_lock(&s->
lock);
319 pthread_mutex_unlock(&s->
lock);
328 AVRational tb = st->time_base;
329 static _Thread_local
char position[12 * 2 + 3 + 1];
331 strncat(position,
" / ",
sizeof position - strlen(position) - 1);
333 position + strlen(position));
348#define CHECK_FF(cmd, action_failed) do { int rc = cmd; if (rc < 0) { char buf[1024]; av_strerror(rc, buf, 1024); log_msg(LOG_LEVEL_ERROR, MOD_NAME #cmd ": %s\n", buf); action_failed} } while(0)
353 if (strstr(
msg->text,
"seek ") != NULL) {
354 const char *count_str =
msg->text + strlen(
"seek ");
356 double sec = strtol(count_str, &endptr, 0);
357 if (endptr[0] !=
's') {
361 AVRational tb = st->time_base;
368 INT64_MAX, AVSEEK_FLAG_FRAME),
374 }
else if (strcmp(
msg->text,
"pause") == 0) {
378 }
else if (strcmp(
msg->text,
"quit") == 0) {
391 AVPacket *pkt, AVFrame *
frame) {
392 s->
last_vid_pts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts;
399 memcpy(out->
tiles[0].
data, pkt->data, pkt->size);
403 int ret = avcodec_send_packet(s->
vid_ctx, pkt);
404 if (ret != 0 && ret != AVERROR(EAGAIN)) {
410 MOD_NAME "Video decompressing %c frame (pts %" PRId64
") "
412 av_get_picture_type_char(
frame->pict_type),
frame->pts,
424 int video_dst_linesize[4] = {
426 uint8_t *dst[4] = {(uint8_t *)out->
tiles[0].
data};
431 video_dst_linesize[0], rgb_shift);
433 sws_scale(s->
sws_ctx, (
const uint8_t *
const *)
frame->data,
438#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 30, 100)
448 AVRational tb = st->time_base;
450 char pts_val[128] =
"NO VALUE";
451 if (pkt->pts != AV_NOPTS_VALUE) {
452 snprintf(pts_val,
sizeof pts_val,
"%" PRId64, pkt->pts);
454 char dts_val[128] =
"NO VALUE";
455 if (pkt->dts != AV_NOPTS_VALUE) {
456 snprintf(dts_val,
sizeof dts_val,
"%" PRId64, pkt->dts);
459 MOD_NAME "rcv %s pkt, ID %d, pos %.2f s (pts %s, dts "
460 "%s, dur %" PRId64
", tb %d/%d), sz %d B\n",
461 av_get_media_type_string(st->codecpar->codec_type),
463 (
double)(pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts) *
465 pts_val, dts_val, pkt->duration, tb.num, tb.den, pkt->size);
468#define FAIL_WORKER { pthread_mutex_lock(&s->lock); s->failed = true; pthread_mutex_unlock(&s->lock); pthread_cond_signal(&s->new_frame_ready); return NULL; }
472 AVPacket *pkt = av_packet_alloc();
473 AVFrame *
frame = av_frame_alloc();
478 pthread_mutex_lock(&s->
lock);
485 pthread_mutex_unlock(&s->
lock);
491 pthread_mutex_unlock(&s->
lock);
494 pthread_mutex_unlock(&s->
lock);
496 av_packet_unref(pkt);
497 int ret = av_read_frame(s->
fmt_ctx, pkt);
498 if (ret == AVERROR_EOF) {
515 pkt, s->
fmt_ctx->streams[pkt->stream_index]);
533 pthread_mutex_lock(&s->
lock);
535 pthread_mutex_unlock(&s->
lock);
540 av_packet_free(&pkt);
541 av_frame_free(&
frame);
547 bool *opportunistic_audio) {
549 strncpy(fmt_cpy,
fmt,
sizeof fmt_cpy - 1);
552 char *saveptr = NULL;
553 while ((
item = strtok_r(tmp,
":", &saveptr)) != NULL) {
561 if (strcmp(
item,
"loop") == 0) {
563 }
else if (strcmp(
item,
"nodecode") == 0) {
565 }
else if (strcmp(
item,
"opportunistic_audio") == 0) {
566 *opportunistic_audio =
true;
567 }
else if (strncmp(
item,
"codec=", strlen(
"codec=")) == 0) {
568 char *codec_name =
item + strlen(
"codec=");
573 }
else if (strncmp(
item,
"queue=", strlen(
"queue=")) == 0) {
575 }
else if (strncmp(
item,
"threads=", strlen(
"threads=")) == 0) {
577 long count = strtol(
item + strlen(
"threads="), &endptr, 0);
579 s->
thread_type = strchr(endptr,
'F') != NULL ? FF_THREAD_FRAME : 0;
580 s->
thread_type |= strchr(endptr,
'S') != NULL ? FF_THREAD_SLICE : 0;
581 }
else if (strstr(
item,
"seek=") ==
item) {
592 AVCodecContext *dec_ctx = avcodec_alloc_context3(dec);
596 dec_ctx->thread_count = thread_count;
597 dec_ctx->thread_type = thread_type;
600 if (avcodec_parameters_to_context(dec_ctx, st->codecpar) < 0) {
602 avcodec_free_context(&dec_ctx);
606 AVDictionary *opts = NULL;
607 av_dict_set(&opts,
"refcounted_frames",
"0", 0);
608 if (avcodec_open2(dec_ctx, dec, &opts) < 0) {
610 avcodec_free_context(&dec_ctx);
618 pthread_mutex_lock(&s->
lock);
620 pthread_mutex_unlock(&s->
lock);
626 pthread_mutex_lock(&s->
lock);
628 pthread_mutex_unlock(&s->
lock);
638 AVRational tb = st->time_base;
639 int64_t
ts = st->start_time + (int64_t) s->
seek_sec * tb.den / tb.num;
641 ts, INT64_MAX, AVSEEK_FLAG_FRAME),
647 case AV_FIELD_UNKNOWN:
649 MOD_NAME "Unknown field order, using progressive.\n");
651 case AV_FIELD_PROGRESSIVE:
658 MOD_NAME "Potentially unsupported field order (lower-"
659 "field first): %d! Using progressive.\n",
669 s->
video_desc.
fps = (double)st->r_frame_rate.num / st->r_frame_rate.den;
677 avcodec_get_name(st->codecpar->codec_id));
683 const AVCodec *dec = avcodec_find_decoder(st->codecpar->codec_id);
691 enum AVPixelFormat suggested[] = {s->
vid_ctx->pix_fmt, AV_PIX_FMT_NONE};
704 enum AVPixelFormat target_pixfmt =
706 if (target_pixfmt == AV_PIX_FMT_NONE) {
708 MOD_NAME "Cannot find suitable AVPixelFormat "
709 "for swscale conversion!\n");
718 MOD_NAME "Cannot find neither UltraGrid nor "
719 "swscale conversion!\n");
727 return file_channels;
731 MOD_NAME "Requested %d channels, file "
732 "contains only %d!\n",
734 return file_channels;
739#define CHECK(call) { int ret = call; if (ret != 0) abort(); }
741 bool opportunistic_audio =
false;
743 char errbuf[1024] =
"";
751#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 12, 100)
754#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(58, 9, 100)
755 avcodec_register_all();
766 s->
thread_type = FF_THREAD_FRAME | FF_THREAD_SLICE;
768 CHECK(pthread_mutex_init(&s->
lock, NULL));
789 if (rc >= 0 && (rc = avformat_find_stream_info(s->
fmt_ctx, NULL)) < 0) {
790 snprintf(errbuf,
sizeof errbuf,
MOD_NAME "Could not find stream information");
800 const AVCodec *dec = NULL;
802 s->
fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, (
void *)&dec, 0);
817 av_get_sample_fmt_name(s->
aud_ctx->sample_fmt));
880 if (vid_frm == NULL) {
894 long drop_samples = 0;
895 if (vid_frm->
seq == UINT32_MAX) {
897 MOD_NAME "Cannot get video PTS or too high!\n");
909 int64_t apts_start = (int64_t)vid_frm->
seq * vtb.num * atb.den /
910 ((int64_t)vtb.den * atb.num);
913 (int64_t)vtb.num * atb.den +
914 ((int64_t)vtb.den * atb.num - 1)) /
915 ((int64_t)vtb.den * atb.num);
917 const int64_t sample_alignment_tb = atb.num * (l / atb.den);
918 const int64_t samples_aligned_tb =
920 sample_alignment_tb * sample_alignment_tb;
921 const int64_t samples =
928 drop_samples = drop_samples < samples / 2 ? 0 : drop_samples;
932 "audio samples: %" PRId64
933 ", drop: %ld, reqB:%d, ring:%d, ast_ts: %" PRIu64
934 ", apts_st: %" PRIu64
", apts_end: %" PRIu64
"\n",
935 samples, drop_samples, ret->
max_size,
947 int64_t samples_written =
952 long drop_bytes = drop_samples * ret->
bps * ret->
ch_count;
959 if (ret && drop_samples > 0) {
962 memmove(ret->
data, ret->
data + drop_bytes,
979 if (aud_frm == NULL) {
984 MSG(WARNING,
"Resynchronizing audio timestamps.\n");
1004 pthread_mutex_lock(&s->
lock);
1010 pthread_mutex_unlock(&s->
lock);
1014 pthread_mutex_unlock(&s->
lock);
1025 gettimeofday(&t, NULL);
1035 *available_cards = NULL;
struct video_frame * frame
struct audio_frame ** audio
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
void vf_data_deleter(struct video_frame *buf)
int vc_get_linesize(unsigned int width, codec_t codec)
struct video_frame * vf_alloc_desc(struct video_desc desc)
Allocates video frame accordig given desc.
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
codec_t get_codec_from_name(const char *name)
This file contains definition of some common audio types.
int color_printf(const char *format,...)
void log_msg(int level, const char *format,...)
void log_msg_once(int level, uint32_t id, const char *msg,...)
#define LOG_LEVEL_NOTICE
information that may be interesting
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_VERBOSE
#define debug_msg(...)
#define debug_msg(...) log_msg(LOG_LEVEL_DEBUG, "[pid/%d +%d %s] ", getpid(), LINE,...
#define LOG_LEVEL_WARNING
less severe errors
av_to_uv_convert_t * get_av_to_uv_conversion(int av_codec, codec_t uv_codec)
codec_t get_best_ug_codec_to_av(const enum AVPixelFormat *fmt, bool use_hwaccel)
void av_to_uv_conversion_destroy(av_to_uv_convert_t **s)
void av_to_uv_convert(const av_to_uv_convert_t *convert, char *dst, AVFrame *in, int width, int height, int pitch, const int rgb_shift[3])
char * strdup_path_with_expansion(const char *orig_path)
void module_init_default(struct module *module_data)
void module_register(struct module *module_data, struct module *parent)
void module_done(struct module *module_data)
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
void register_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
void unregister_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
unsigned int audio_capture_channels
codec_t get_av_to_ug_codec(enum AVCodecID av_codec)
void print_decoder_error(const char *mod_name, int rc)
void print_libav_error(int verbosity, const char *msg, int rc)
#define AVCODECCTX_CHANNELS(context)
@ LIBRARY_CLASS_VIDEO_CAPTURE
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
void simple_linked_list_append(struct simple_linked_list *l, void *data)
void simple_linked_list_prepend(struct simple_linked_list *l, void *data)
int simple_linked_list_size(struct simple_linked_list *l)
struct simple_linked_list * simple_linked_list_init(void)
void simple_linked_list_destroy(struct simple_linked_list *l)
void * simple_linked_list_pop(struct simple_linked_list *l)
#define CLAMP(x, low, high)
#define IS_KEY_PREFIX(tok, key)
expands to true value if <k> from tok in format <k>=<v> is prefix of key
#define IF_NOT_NULL_ELSE(val, default_val)
long long lcm(long long a, long long b)
void free_message(struct message *msg, struct response *r)
struct response * new_response(int status, const char *text)
struct message * check_message(struct module *mod)
#define RESPONSE_BAD_REQUEST
#define DEFAULT_RGB_SHIFT_INIT
void playback_register_keyboard_ctl(struct module *mod)
int ring_get_current_size(struct ring_buffer *ring)
void ring_buffer_destroy(struct ring_buffer *ring)
struct ring_buffer * ring_buffer_init(int size)
void ring_buffer_flush(struct ring_buffer *buf)
int ring_buffer_read(struct ring_buffer *ring, char *out, int max_len)
void ring_buffer_write(struct ring_buffer *ring, const char *in, int len)
struct used to comunicate with audio capture/playback device
void(* dispose)(struct audio_frame *)
called by sender when frame was processed
uint32_t priv_magic
optional magic number that can a module set
notify_t new_message
if set, notifies module that new message is in queue, receiver lock is hold during the call
char * data
Raw tile data. Pointer must be at least 4B aligned.
unsigned int data_len
length of the data
struct timeval last_stream_stat
struct video_desc video_desc
pthread_cond_t frame_consumed
struct timeval last_frame
pthread_cond_t new_frame_ready
AVFormatContext * fmt_ctx
struct ring_buffer * audio_data
struct audio_desc audio_desc
struct simple_linked_list * vid_frm_noaud
struct simple_linked_list * video_frame_queue
av_to_uv_convert_t * conv_uv
pthread_mutex_t audio_frame_lock
struct SwsContext * sws_ctx
int64_t last_vid_pts
last played PTS, if PTS == PTS_NO_VALUE, DTS is stored instead
enum interlacing_t interlacing
unsigned int width
width of every tile (!)
unsigned int height
height of every tile (!)
void(* data_deleter)(struct video_frame *)
void(* dispose)(struct video_frame *)
Struct video_frame represents a video frame and contains video description.
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
uint32_t seq
seq num, used internally by JPEG enc, file cap
uint32_t duration
used by file cap
struct video_frame_callbacks callbacks
void set_thread_name(const char *name)
void format_time_ms(uint64_t ts, char buf[static FORMAT_TIME_MS_BUF_LEN])
double tv_diff(struct timeval curr_time, struct timeval prev_time)
static time_ns_t get_time_in_ns()
This file contains some common data types.
@ TIMESTAMP_VALID
timestamp set by source (in 90 kHz clock)
@ kHz90
timestamp time base
@ PROGRESSIVE
progressive frame
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
@ VIDEO_CODEC_NONE
dummy color spec
enum AVPixelFormat get_ug_to_av_pixfmt(codec_t ug_codec)
void float2int(char *out, const char *in, int len)
void audio_frame_write_desc(struct audio_frame *f, struct audio_desc desc)
void mux_channel(char *out, const char *in, int bps, int in_len, int out_stream_channels, int pos_in_stream, double scale)
const char * audio_desc_to_cstring(struct audio_desc desc)
const char * video_desc_to_string(struct video_desc d)
This is an umbrella header for video functions.
static enum interlacing_t get_field_order(enum AVFieldOrder av_fo)
static const struct video_capture_info vidcap_file_info
static bool setup_video(struct vidcap_state_lavf_decoder *s)
static struct audio_frame * get_audio(struct vidcap_state_lavf_decoder *s, const struct video_frame *vid_frm)
#define CHECK_FF(cmd, action_failed)
static struct video_frame * vidcap_file_grab(void *state, struct audio_frame **audio)
static void * vidcap_file_worker(void *state)
static bool have_audio_for_video(struct vidcap_state_lavf_decoder *s, int64_t vid_frm_ts, int64_t vid_frm_dur)
static void vidcap_file_show_help(bool full)
static void vidcap_file_dispose_audio(struct audio_frame *f)
static void print_current_pos(struct vidcap_state_lavf_decoder *s, struct timeval t)
static struct video_frame * process_video_pkt(struct vidcap_state_lavf_decoder *s, AVPacket *pkt, AVFrame *frame)
static int vidcap_file_init(struct vidcap_params *params, void **state)
static void flush_captured_data(struct vidcap_state_lavf_decoder *s)
static void vidcap_file_common_cleanup(struct vidcap_state_lavf_decoder *s)
static void vidcap_file_done(void *state)
static void vidcap_file_process_audio_pkt(struct vidcap_state_lavf_decoder *s, AVPacket *pkt, AVFrame *frame)
static struct audio_frame * get_timestamped_audio(struct vidcap_state_lavf_decoder *s, const struct video_frame *vid_frm)
static bool vidcap_file_parse_fmt(struct vidcap_state_lavf_decoder *s, const char *fmt, bool *opportunistic_audio)
static void vidcap_file_write_audio(struct vidcap_state_lavf_decoder *s, AVFrame *frame)
static int get_ach_count(int file_channels)
static const double AUDIO_RATIO
at this ratio the audio frame can be longer than the video frame
static void print_packet_info(const AVPacket *pkt, const AVStream *st)
static void vidcap_file_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
static void seek_start(struct vidcap_state_lavf_decoder *s)
static void vidcap_file_process_messages(struct vidcap_state_lavf_decoder *s)
static AVCodecContext * vidcap_file_open_dec_ctx(const AVCodec *dec, AVStream *st, int thread_count, int thread_type)
static const char * get_current_position_str(struct vidcap_state_lavf_decoder *s)
static void vidcap_file_should_exit(void *state)
static void vidcap_file_new_message(struct module *mod)
struct module * vidcap_params_get_parent(const struct vidcap_params *params)
const char * vidcap_params_get_fmt(const struct vidcap_params *params)
unsigned int vidcap_params_get_flags(const struct vidcap_params *params)
#define VIDCAP_FLAG_AUDIO_ANY
#define VIDEO_FRAME_DISPOSE(frame)