New upstream version 26.1.0+dfsg1

This commit is contained in:
Sebastian Ramacher 2020-12-22 18:32:50 +01:00
parent 040dcc3fc2
commit 013818c4af
594 changed files with 19576 additions and 4478 deletions

View file

@ -1,5 +1,9 @@
project(obs-ffmpeg-mux)
if(DEBUG_FFMPEG_MUX)
add_definitions(-DDEBUG_FFMPEG)
endif()
find_package(FFmpeg REQUIRED
COMPONENTS avcodec avutil avformat)
include_directories(${FFMPEG_INCLUDE_DIRS})
@ -15,6 +19,7 @@ add_executable(obs-ffmpeg-mux
${obs-ffmpeg-mux_HEADERS})
target_link_libraries(obs-ffmpeg-mux
libobs
${FFMPEG_LIBRARIES})
set_target_properties(obs-ffmpeg-mux PROPERTIES FOLDER "plugins/obs-ffmpeg")

View file

@ -22,13 +22,17 @@
#endif
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "ffmpeg-mux.h"
#include <util/dstr.h>
#include <libavformat/avformat.h>
#define ANSI_COLOR_RED "\x1b[0;91m"
#define ANSI_COLOR_MAGENTA "\x1b[0;95m"
#define ANSI_COLOR_RESET "\x1b[0m"
#if LIBAVCODEC_VERSION_MAJOR >= 58
#define CODEC_FLAG_GLOBAL_H AV_CODEC_FLAG_GLOBAL_HEADER
#else
@ -37,6 +41,8 @@
/* ------------------------------------------------------------------------- */
static char *global_stream_key = "";
struct resize_buf {
uint8_t *buf;
size_t size;
@ -70,6 +76,8 @@ static inline void resize_buf_free(struct resize_buf *rb)
struct main_params {
char *file;
/* printable_file is file with any stream key information removed */
struct dstr printable_file;
int has_video;
int tracks;
char *vcodec;
@ -172,6 +180,8 @@ static void ffmpeg_mux_free(struct ffmpeg_mux *ffm)
free(ffm->audio);
}
dstr_free(&ffm->params.printable_file);
memset(ffm, 0, sizeof(*ffm));
}
@ -218,6 +228,44 @@ static bool get_audio_params(struct audio_params *audio, int *argc,
return true;
}
static void ffmpeg_log_callback(void *param, int level, const char *format,
va_list args)
{
#ifdef DEBUG_FFMPEG
char out_buffer[4096];
struct dstr out = {0};
vsnprintf(out_buffer, sizeof(out_buffer), format, args);
dstr_copy(&out, out_buffer);
dstr_replace(&out, global_stream_key, "{stream_key}");
switch (level) {
case AV_LOG_INFO:
fprintf(stdout, "info: [ffmpeg_muxer] %s", out.array);
fflush(stdout);
break;
case AV_LOG_WARNING:
fprintf(stdout, "%swarning: [ffmpeg_muxer] %s%s",
ANSI_COLOR_MAGENTA, out.array, ANSI_COLOR_RESET);
fflush(stdout);
break;
case AV_LOG_ERROR:
fprintf(stderr, "%serror: [ffmpeg_muxer] %s%s", ANSI_COLOR_RED,
out.array, ANSI_COLOR_RESET);
fflush(stderr);
}
dstr_free(&out);
#else
UNUSED_PARAMETER(level);
UNUSED_PARAMETER(format);
UNUSED_PARAMETER(args);
#endif
UNUSED_PARAMETER(param);
}
static bool init_params(int *argc, char ***argv, struct main_params *params,
struct audio_params **p_audio)
{
@ -287,6 +335,16 @@ static bool init_params(int *argc, char ***argv, struct main_params *params,
*p_audio = audio;
dstr_copy(&params->printable_file, params->file);
get_opt_str(argc, argv, &global_stream_key, "stream key");
if (strcmp(global_stream_key, "") != 0) {
dstr_replace(&params->printable_file, global_stream_key,
"{stream_key}");
}
av_log_set_callback(ffmpeg_log_callback);
get_opt_str(argc, argv, &params->muxer_settings, "muxer settings");
return true;
@ -353,6 +411,10 @@ static void create_video_stream(struct ffmpeg_mux *ffm)
(AVRational){ffm->params.fps_den, ffm->params.fps_num};
ffm->video_stream->time_base = context->time_base;
#if LIBAVFORMAT_VERSION_MAJOR < 59
// codec->time_base may still be used if LIBAVFORMAT_VERSION_MAJOR < 59
ffm->video_stream->codec->time_base = context->time_base;
#endif
ffm->video_stream->avg_frame_rate = av_inv_q(context->time_base);
if (ffm->output->oformat->flags & AVFMT_GLOBALHEADER)
@ -521,7 +583,8 @@ static inline int open_output_file(struct ffmpeg_mux *ffm)
AVIO_FLAG_WRITE);
if (ret < 0) {
fprintf(stderr, "Couldn't open '%s', %s\n",
ffm->params.file, av_err2str(ret));
ffm->params.printable_file.array,
av_err2str(ret));
return FFM_ERROR;
}
}
@ -548,8 +611,8 @@ static inline int open_output_file(struct ffmpeg_mux *ffm)
ret = avformat_write_header(ffm->output, &dict);
if (ret < 0) {
fprintf(stderr, "Error opening '%s': %s\n", ffm->params.file,
av_err2str(ret));
fprintf(stderr, "Error opening '%s': %s",
ffm->params.printable_file.array, av_err2str(ret));
av_dict_free(&dict);
@ -564,29 +627,43 @@ static inline int open_output_file(struct ffmpeg_mux *ffm)
#define SRT_PROTO "srt"
#define UDP_PROTO "udp"
#define TCP_PROTO "tcp"
#define HTTP_PROTO "http"
static bool ffmpeg_mux_is_network(struct ffmpeg_mux *ffm)
{
return !strncmp(ffm->params.file, SRT_PROTO, sizeof(SRT_PROTO) - 1) ||
!strncmp(ffm->params.file, UDP_PROTO, sizeof(UDP_PROTO) - 1) ||
!strncmp(ffm->params.file, TCP_PROTO, sizeof(TCP_PROTO) - 1) ||
!strncmp(ffm->params.file, HTTP_PROTO, sizeof(HTTP_PROTO) - 1);
}
static int ffmpeg_mux_init_context(struct ffmpeg_mux *ffm)
{
AVOutputFormat *output_format;
int ret;
bool isNetwork = false;
if (strncmp(ffm->params.file, SRT_PROTO, sizeof(SRT_PROTO) - 1) == 0 ||
strncmp(ffm->params.file, UDP_PROTO, sizeof(UDP_PROTO) - 1) == 0 ||
strncmp(ffm->params.file, TCP_PROTO, sizeof(TCP_PROTO) - 1) == 0)
isNetwork = true;
bool is_http = false;
is_http = (strncmp(ffm->params.file, HTTP_PROTO,
sizeof(HTTP_PROTO) - 1) == 0);
if (isNetwork) {
bool is_network = ffmpeg_mux_is_network(ffm);
if (is_network) {
avformat_network_init();
output_format = av_guess_format("mpegts", NULL, "video/M2PT");
} else {
output_format = av_guess_format(NULL, ffm->params.file, NULL);
}
if (is_network && !is_http)
output_format = av_guess_format("mpegts", NULL, "video/M2PT");
else
output_format = av_guess_format(NULL, ffm->params.file, NULL);
if (output_format == NULL) {
fprintf(stderr, "Couldn't find an appropriate muxer for '%s'\n",
ffm->params.file);
ffm->params.printable_file.array);
return FFM_ERROR;
}
printf("info: Output format name and long_name: %s, %s\n",
output_format->name ? output_format->name : "unknown",
output_format->long_name ? output_format->long_name : "unknown");
ret = avformat_alloc_output_context2(&ffm->output, output_format, NULL,
ffm->params.file);
@ -726,8 +803,13 @@ static inline bool ffmpeg_mux_packet(struct ffmpeg_mux *ffm, uint8_t *buf,
int ret = av_interleaved_write_frame(ffm->output, &packet);
if (ret < 0) {
fprintf(stderr, "av_interleaved_write_frame failed: %s\n",
av_err2str(ret));
fprintf(stderr, "av_interleaved_write_frame failed: %d: %s\n",
ret, av_err2str(ret));
}
/* Treat "Invalid data found when processing input" and "Invalid argument" as non-fatal */
if (ret == AVERROR_INVALIDDATA || ret == EINVAL) {
return true;
}
return ret >= 0;

View file

@ -16,6 +16,7 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
enum ffm_packet_type {