mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-29 06:34:19 +00:00
FS-7505: clean up and support multiple formats to same extensions {modname=mod_vlc}rtmp://foo.com/flvplayback also move [/tmp]file to be {spool_path=/tmp}
This commit is contained in:
1 parent
13e60c420d
commit
52d15f6398
9 files changed
+292
-173
No files matched your search
@@ -6697,7 +6697,7 @@ static void *SWITCH_THREAD_FUNC conference_record_thread_run(switch_thread_t *th
|
||||
|
||||
if (conference->members_with_video && switch_test_flag(conference, CFLAG_TRANSCODE_VIDEO)) {
|
||||
flags |= SWITCH_FILE_FLAG_VIDEO;
|
||||
if (*rec->path != '{' && conference->canvas) {
|
||||
if (conference->canvas) {
|
||||
char *orig_path = rec->path;
|
||||
rec->path = switch_core_sprintf(rec->pool, "{channels=%d,samplerate=%d,vw=%d,vh=%d,fps=%0.2f}%s",
|
||||
conference->channels,
|
||||
|
||||
@@ -171,7 +171,7 @@ static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AV
|
||||
}
|
||||
|
||||
/* Add an output stream. */
|
||||
static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id)
|
||||
static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCodec **codec, enum AVCodecID codec_id, switch_mm_t *mm)
|
||||
{
|
||||
AVCodecContext *c;
|
||||
switch_status_t status = SWITCH_STATUS_FALSE;
|
||||
@@ -203,11 +203,21 @@ static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCode
|
||||
c->sample_rate = ost->sample_rate = 44100;
|
||||
c->channels = ost->channels;
|
||||
c->channel_layout = av_get_default_channel_layout(c->channels);
|
||||
|
||||
if (mm) {
|
||||
if (mm->ab) {
|
||||
c->bit_rate = mm->ab * 1024;
|
||||
}
|
||||
if (mm->samplerate) {
|
||||
c->sample_rate = ost->sample_rate = mm->samplerate;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AVMEDIA_TYPE_VIDEO:
|
||||
c->codec_id = codec_id;
|
||||
c->bit_rate = 450000;
|
||||
c->bit_rate = 1000000;
|
||||
/* Resolution must be a multiple of two. */
|
||||
c->width = ost->width;
|
||||
c->height = ost->height;
|
||||
@@ -220,6 +230,16 @@ static switch_status_t add_stream(OutputStream *ost, AVFormatContext *oc, AVCode
|
||||
if (codec_id == AV_CODEC_ID_VP8) {
|
||||
av_set_options_string(c, "quality=realtime", "=", ":");
|
||||
}
|
||||
|
||||
if (mm) {
|
||||
if (mm->vb) {
|
||||
c->bit_rate = mm->vb * 1000;
|
||||
}
|
||||
if (mm->keyint) {
|
||||
c->gop_size = mm->keyint;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -307,8 +327,8 @@ static switch_status_t open_audio(AVFormatContext *oc, AVCodec *codec, OutputStr
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_rate: %d nb_samples: %d\n", ost->frame->sample_rate, ost->frame->nb_samples);
|
||||
|
||||
// disable resampler for now before we figure out the correct params
|
||||
if (0 && c->sample_fmt != AV_SAMPLE_FMT_S16) {
|
||||
|
||||
if (c->sample_fmt != AV_SAMPLE_FMT_S16) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "sample_fmt %d != AV_SAMPLE_FMT_S16, start resampler\n", c->sample_fmt);
|
||||
|
||||
ost->resample_ctx = avresample_alloc_context();
|
||||
@@ -402,7 +422,7 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
|
||||
continue;
|
||||
}
|
||||
|
||||
switch_mutex_lock(eh->mutex);
|
||||
//switch_mutex_lock(eh->mutex);
|
||||
|
||||
eh->in_callback = 1;
|
||||
|
||||
@@ -435,12 +455,14 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
|
||||
}
|
||||
|
||||
if (got_packet) {
|
||||
switch_mutex_lock(eh->mutex);
|
||||
ret = write_frame(eh->oc, &eh->video_st->st->codec->time_base, eh->video_st->st, &pkt);
|
||||
switch_mutex_unlock(eh->mutex);
|
||||
av_free_packet(&pkt);
|
||||
}
|
||||
|
||||
eh->in_callback = 0;
|
||||
switch_mutex_unlock(eh->mutex);
|
||||
//switch_mutex_unlock(eh->mutex);
|
||||
}
|
||||
|
||||
switch_img_free(&last_img);
|
||||
@@ -586,7 +608,7 @@ SWITCH_STANDARD_APP(record_av_function)
|
||||
video_st.width = vid_params.width;
|
||||
video_st.height = vid_params.height;
|
||||
video_st.next_pts = switch_time_now() / 1000;
|
||||
if (add_stream(&video_st, oc, &video_codec, fmt->video_codec) == SWITCH_STATUS_SUCCESS &&
|
||||
if (add_stream(&video_st, oc, &video_codec, fmt->video_codec, NULL) == SWITCH_STATUS_SUCCESS &&
|
||||
open_video(oc, video_codec, &video_st) == SWITCH_STATUS_SUCCESS) {
|
||||
avcodec_string(codec_str, sizeof(codec_str), video_st.st->codec, 1);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "use video codec implementation %s\n", codec_str);
|
||||
@@ -598,7 +620,7 @@ SWITCH_STANDARD_APP(record_av_function)
|
||||
audio_st.channels = read_impl.number_of_channels;
|
||||
audio_st.sample_rate = force_sample_rate;
|
||||
|
||||
add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec);
|
||||
add_stream(&audio_st, oc, &audio_codec, fmt->audio_codec, NULL);
|
||||
if (open_audio(oc, audio_codec, &audio_st) != SWITCH_STATUS_SUCCESS) {
|
||||
goto end;
|
||||
}
|
||||
@@ -1037,7 +1059,8 @@ static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
|
||||
{
|
||||
switch_log_level_t switch_level = SWITCH_LOG_DEBUG;
|
||||
|
||||
if (level > AV_LOG_INFO) return;
|
||||
/* naggy messages */
|
||||
if (level == AV_LOG_DEBUG || level == AV_LOG_WARNING) return;
|
||||
|
||||
switch(level) {
|
||||
case AV_LOG_QUIET: switch_level = SWITCH_LOG_CONSOLE; break;
|
||||
@@ -1112,7 +1135,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
|
||||
|
||||
memset(context, 0, sizeof(av_file_context_t));
|
||||
|
||||
context->offset = 0; // 1200 ?
|
||||
context->offset = 1200;
|
||||
if (handle->params && (tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
|
||||
context->offset = atoi(tmp);
|
||||
}
|
||||
@@ -1170,6 +1193,38 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
|
||||
if (fmt->audio_codec != AV_CODEC_ID_AAC) {
|
||||
fmt->audio_codec = AV_CODEC_ID_AAC; // force AAC
|
||||
}
|
||||
|
||||
|
||||
handle->mm.samplerate = 44100;
|
||||
handle->mm.ab = 128;
|
||||
|
||||
if (handle->mm.vw && handle->mm.vh) {
|
||||
switch(handle->mm.vh) {
|
||||
case 240:
|
||||
handle->mm.vb = 400;
|
||||
break;
|
||||
case 360:
|
||||
handle->mm.vb = 750;
|
||||
break;
|
||||
case 480:
|
||||
handle->mm.vb = 1000;
|
||||
break;
|
||||
case 720:
|
||||
handle->mm.vb = 2500;
|
||||
break;
|
||||
case 1080:
|
||||
handle->mm.vb = 4500;
|
||||
break;
|
||||
default:
|
||||
handle->mm.vb = (handle->mm.vw * handle->mm.vh) / 175;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle->mm.fps > 0.0f) {
|
||||
handle->mm.keyint = (int) 2.0f * handle->mm.fps;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
desc = avcodec_descriptor_get(fmt->video_codec);
|
||||
@@ -1181,7 +1236,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
|
||||
context->audio_st.channels = handle->channels;
|
||||
context->audio_st.sample_rate = handle->samplerate;
|
||||
|
||||
add_stream(&context->audio_st, context->oc, &context->audio_codec, fmt->audio_codec);
|
||||
add_stream(&context->audio_st, context->oc, &context->audio_codec, fmt->audio_codec, &handle->mm);
|
||||
if (open_audio(context->oc, context->audio_codec, &context->audio_st) != SWITCH_STATUS_SUCCESS) {
|
||||
goto end;
|
||||
}
|
||||
@@ -1292,22 +1347,22 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
|
||||
context->offset = 0;
|
||||
}
|
||||
|
||||
if (context->mutex) switch_mutex_lock(context->mutex);
|
||||
|
||||
|
||||
switch_buffer_write(context->audio_buffer, data, datalen);
|
||||
bytes = context->audio_st.frame->nb_samples * 2 * context->audio_st.st->codec->channels;
|
||||
inuse = switch_buffer_inuse(context->audio_buffer);
|
||||
|
||||
while (inuse >= bytes) {
|
||||
//inuse = switch_buffer_inuse(context->audio_buffer);
|
||||
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "inuse: %d samples: %d bytes: %d\n", inuse, context->audio_st.frame->nb_samples, bytes);
|
||||
|
||||
while ((inuse = switch_buffer_inuse(context->audio_buffer)) >= bytes) {
|
||||
AVPacket pkt = { 0 };
|
||||
int got_packet = 0;
|
||||
int ret;
|
||||
|
||||
av_init_packet(&pkt);
|
||||
|
||||
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "inuse: %d samples: %d bytes: %d\n", inuse, audio_st.frame->nb_samples, bytes);
|
||||
|
||||
if (0 && context->audio_st.resample_ctx) { // need resample
|
||||
if (context->audio_st.resample_ctx) { // need resample
|
||||
int out_samples = avresample_get_out_samples(context->audio_st.resample_ctx, context->audio_st.frame->nb_samples);
|
||||
|
||||
av_frame_make_writable(context->audio_st.frame);
|
||||
@@ -1321,7 +1376,6 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
|
||||
if (ret < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while converting %d samples, error text: %s\n",
|
||||
context->audio_st.frame->nb_samples, get_error_text(ret));
|
||||
inuse = switch_buffer_inuse(context->audio_buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1340,22 +1394,21 @@ static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, s
|
||||
|
||||
if (ret < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error encoding audio frame: %d\n", ret);
|
||||
inuse = switch_buffer_inuse(context->audio_buffer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (got_packet) {
|
||||
if (context->mutex) switch_mutex_lock(context->mutex);
|
||||
ret = write_frame(context->oc, &context->audio_st.st->codec->time_base, context->audio_st.st, &pkt);
|
||||
if (context->mutex) switch_mutex_unlock(context->mutex);
|
||||
if (ret < 0) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Error while writing audio frame: %s\n", get_error_text(ret));
|
||||
switch_goto_status(SWITCH_STATUS_FALSE, end);
|
||||
}
|
||||
}
|
||||
|
||||
inuse = switch_buffer_inuse(context->audio_buffer);
|
||||
}
|
||||
|
||||
if (context->mutex) switch_mutex_unlock(context->mutex);
|
||||
|
||||
|
||||
end:
|
||||
return status;
|
||||
@@ -1379,7 +1432,7 @@ static switch_status_t av_file_write_video(switch_file_handle_t *handle, switch_
|
||||
context->video_st.width = frame->img->d_w;
|
||||
context->video_st.height = frame->img->d_h;
|
||||
context->video_st.next_pts = switch_time_now() / 1000;
|
||||
if (add_stream(&context->video_st, context->oc, &context->video_codec, context->oc->oformat->video_codec) == SWITCH_STATUS_SUCCESS &&
|
||||
if (add_stream(&context->video_st, context->oc, &context->video_codec, context->oc->oformat->video_codec, &handle->mm) == SWITCH_STATUS_SUCCESS &&
|
||||
open_video(context->oc, context->video_codec, &context->video_st) == SWITCH_STATUS_SUCCESS) {
|
||||
|
||||
char codec_str[256];
|
||||
|
||||
@@ -62,7 +62,7 @@ typedef int (*imem_get_t)(void *data, const char *cookie,
|
||||
typedef void (*imem_release_t)(void *data, const char *cookie, size_t, void *);
|
||||
|
||||
/* Change value to -vvv for vlc related debug. Be careful since vlc is at least as verbose as FS about logging */
|
||||
const char *vlc_args[] = {"-vvvv"};
|
||||
const char *vlc_args[] = {"-v"};
|
||||
//const char *vlc_args[] = {"--network-caching=0"};
|
||||
//--sout-mux-caching
|
||||
|
||||
@@ -158,9 +158,10 @@ void log_cb(void *data, int level, const libvlc_log_t *ctx, const char *fmt, va_
|
||||
switch_log_level_t fslevel = SWITCH_LOG_DEBUG;
|
||||
int ret;
|
||||
|
||||
ret = switch_vasprintf(&ldata, fmt, args);
|
||||
|
||||
if (ret == -1) return;
|
||||
/* vlc abuses logging too much these leves spew nonsense (comment to do deep testing) */
|
||||
if (level == LIBVLC_DEBUG || level == LIBVLC_WARNING) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(level) {
|
||||
case LIBVLC_NOTICE:
|
||||
@@ -174,11 +175,19 @@ void log_cb(void *data, int level, const libvlc_log_t *ctx, const char *fmt, va_
|
||||
break;
|
||||
case LIBVLC_DEBUG:
|
||||
default:
|
||||
fslevel = SWITCH_LOG_DEBUG;
|
||||
fslevel = SWITCH_LOG_DEBUG1;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = switch_vasprintf(&ldata, fmt, args);
|
||||
|
||||
if (ret == -1) return;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, fslevel, "%s\n", ldata);
|
||||
if (end_of(ldata) == '\n') {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, fslevel, "VLC: %s", ldata);
|
||||
} else {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG_CLEAN, fslevel, "VLC: %s\n", ldata);
|
||||
}
|
||||
|
||||
switch_safe_free(ldata);
|
||||
}
|
||||
@@ -753,17 +762,8 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
|
||||
char *ext = NULL;
|
||||
switch_file_t *fd = NULL;
|
||||
const char *realpath = NULL;
|
||||
float fps = 0.0f;
|
||||
int is_stream = 0;
|
||||
int samplerate = 44100;
|
||||
int channels = 1;
|
||||
int keyint = 60;
|
||||
int ab = 0;
|
||||
int vb = 0;
|
||||
int vw = 0;
|
||||
int vh = 0;
|
||||
int tmp;
|
||||
const char *val;
|
||||
|
||||
|
||||
context = switch_core_alloc(handle->memory_pool, sizeof(*context));
|
||||
context->pool = handle->memory_pool;
|
||||
@@ -772,50 +772,6 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
|
||||
|
||||
realpath = path;
|
||||
|
||||
if (handle->params) {
|
||||
if ((val = switch_event_get_header(handle->params, "samplerate"))) {
|
||||
tmp = atoi(val);
|
||||
if (tmp > 8000) {
|
||||
samplerate = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_event_get_header(handle->params, "channels"))) {
|
||||
tmp = atoi(val);
|
||||
if (tmp == 1 || tmp == 2) {
|
||||
channels = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_event_get_header(handle->params, "ab"))) {
|
||||
tmp = atoi(val);
|
||||
if (tmp > 16) {
|
||||
ab = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_event_get_header(handle->params, "vw"))) {
|
||||
tmp = atoi(val);
|
||||
if (tmp > 0) {
|
||||
vw = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_event_get_header(handle->params, "vh"))) {
|
||||
tmp = atoi(val);
|
||||
if (tmp > 0) {
|
||||
vh = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if ((val = switch_event_get_header(handle->params, "fps"))) {
|
||||
float ftmp = atof(val);
|
||||
if (ftmp > 0.0f) {
|
||||
fps = ftmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO) && switch_test_flag(handle, SWITCH_FILE_FLAG_WRITE)) {
|
||||
if ((ext = strrchr(path, '.')) && !strcasecmp(ext, ".mp4")) {
|
||||
@@ -823,34 +779,34 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
|
||||
path = switch_core_sprintf(context->pool, "#transcode{vcodec=h264,acodec=mp3}:std{access=file,mux=mp4,dst=%s}", path);
|
||||
} else if (handle->stream_name && (!strcasecmp(handle->stream_name, "rtmp") || !strcasecmp(handle->stream_name, "youtube"))) {
|
||||
|
||||
samplerate = 44100;
|
||||
ab = 128;
|
||||
handle->mm.samplerate = 44100;
|
||||
handle->mm.ab = 128;
|
||||
|
||||
if (vw && vh) {
|
||||
switch(vh) {
|
||||
if (handle->mm.vw && handle->mm.vh) {
|
||||
switch(handle->mm.vh) {
|
||||
case 240:
|
||||
vb = 400;
|
||||
handle->mm.vb = 400;
|
||||
break;
|
||||
case 360:
|
||||
vb = 750;
|
||||
handle->mm.vb = 750;
|
||||
break;
|
||||
case 480:
|
||||
vb = 1000;
|
||||
handle->mm.vb = 1000;
|
||||
break;
|
||||
case 720:
|
||||
vb = 2500;
|
||||
handle->mm.vb = 2500;
|
||||
break;
|
||||
case 1080:
|
||||
vb = 4500;
|
||||
handle->mm.vb = 4500;
|
||||
break;
|
||||
default:
|
||||
vb = (vw * vh) / 175;
|
||||
handle->mm.vb = (handle->mm.vw * handle->mm.vh) / 175;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (fps > 0.0f) {
|
||||
keyint = (int) 2.0f * fps;
|
||||
if (handle->mm.fps > 0.0f) {
|
||||
handle->mm.keyint = (int) 2.0f * handle->mm.fps;
|
||||
}
|
||||
|
||||
path = switch_core_sprintf(context->pool,
|
||||
@@ -868,7 +824,7 @@ static switch_status_t vlc_file_open(switch_file_handle_t *handle, const char *p
|
||||
"mux=flv,"
|
||||
"dst=rtmp://%s"
|
||||
"}",
|
||||
keyint, ab, vb, channels, samplerate, path);
|
||||
handle->mm.keyint, handle->mm.ab, handle->mm.vb, handle->mm.channels, handle->mm.samplerate, path);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user