AVFormatContext *fc;
MediaStream *video_st;
switch_timer_t *timer;
- switch_timer_t *other_timer;
int in_callback;
switch_queue_t *video_queue;
switch_thread_t *video_thread;
c->channels = mst->channels;
c->channel_layout = av_get_default_channel_layout(c->channels);
- mst->st->time_base.den = 1000;
- mst->st->time_base.num = 1;
- c->time_base.den = 1000;
- c->time_base.num = 1;
-
if (mm) {
if (mm->ab) {
c->bit_rate = mm->ab * 1024;
static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *obj)
{
record_helper_t *eh = (record_helper_t *) obj;
- void *pop;
- switch_image_t *img, *last_img = NULL, *tmp_img = NULL;
- switch_size_t size;
+ void *pop = NULL;
+ switch_image_t *img = NULL, *tmp_img = NULL;
+ int d_w = 0, d_h = 0;
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_NOTICE, "video thread start\n");
for(;;) {
AVPacket pkt = { 0 };
int got_packet;
- int ret = -1, popped = 0;
+ int ret = -1;
- do {
- switch_status_t status;
- img = NULL;
-
- if (!popped) {
- status = switch_queue_pop(eh->video_queue, &pop);
- popped++;
- } else {
- status = switch_queue_trypop(eh->video_queue, &pop);
+ if (switch_queue_pop(eh->video_queue, &pop) == SWITCH_STATUS_SUCCESS) {
+ if (!pop) {
+ goto endfor;
}
-
- if (status == SWITCH_STATUS_SUCCESS) {
- switch_img_free(&img);
-
- if (!pop) {
- goto endfor;
- }
- img = (switch_image_t *)pop;
- } else {
- if (img) {
- break;
- } else {
- popped = 0;
- continue;
- }
- }
-
- size = switch_queue_size(eh->video_queue);
- } while(img && size > 1);
+ img = (switch_image_t *) pop;
+ if (!d_w) d_w = img->d_w;
+ if (!d_h) d_h = img->d_h;
- if (last_img && (last_img->d_w != img->d_w || last_img->d_h != img->d_h)) {
- /* scale to match established stream */
- switch_img_scale(img, &tmp_img, last_img->d_w, last_img->d_h);
- switch_img_free(&img);
- img = tmp_img;
- tmp_img = NULL;
+ if (d_w && d_h && (d_w != img->d_w || d_h != img->d_h)) {
+ /* scale to match established stream */
+ switch_img_scale(img, &tmp_img, d_w, d_h);
+ switch_img_free(&img);
+ img = tmp_img;
+ tmp_img = NULL;
+ }
+ } else {
+ continue;
}
- switch_img_free(&last_img);
- last_img = img;
-
//switch_mutex_lock(eh->mutex);
eh->in_callback = 1;
fill_avframe(eh->video_st->frame, img);
switch_core_timer_sync(eh->timer);
- if (eh->other_timer) {
- if (eh->timer->samplecount > eh->other_timer->samplecount) {
- int sleepfor = (eh->timer->samplecount - eh->other_timer->samplecount) * 1000;
- switch_yield(sleepfor);
- switch_core_timer_sync(eh->timer);
- }
- }
-
if (eh->video_st->frame->pts == eh->timer->samplecount) {
// never use the same pts, or the encoder coughs
eh->video_st->frame->pts++;
endfor:
- switch_img_free(&last_img);
-
while(switch_queue_trypop(eh->video_queue, &pop) == SWITCH_STATUS_SUCCESS) {
if (!pop) break;
img = (switch_image_t *) pop;
switch_queue_push(eh->video_queue, img);
}
- return SWITCH_STATUS_SUCCESS;;
+ return SWITCH_STATUS_SUCCESS;
}
static void close_stream(AVFormatContext *fc, MediaStream *mst)
switch_buffer_t *buf;
switch_buffer_t *audio_buffer;
switch_timer_t video_timer;
- switch_timer_t audio_timer;
int offset;
int audio_start;
int vid_ready;
AVPacket pkt = { 0 };
int got_data = 0;
int error;
+ int sync = 0;
context->file_read_thread_running = 1;
-#define AUDIO_BUF_SEC 1
+#define AUDIO_BUF_SEC 5
while (context->file_read_thread_running) {
if (switch_buffer_inuse(context->audio_buffer) > AUDIO_BUF_SEC * context->audio_st.sample_rate * context->audio_st.channels * 2) {
- switch_yield(100000);
+ switch_yield(10000);
continue;
}
-
+
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
if (context->has_video && pkt.stream_index == context->video_st.st->index) {
AVFrame *vframe = av_frame_alloc();
switch_image_t *img;
-
+ if (!sync) {
+ switch_buffer_zero(context->audio_buffer);
+ sync = 1;
+ }
switch_assert(vframe);
if ((error = avcodec_decode_video2(context->video_st.st->codec, vframe, &got_data, &pkt)) < 0) {
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "pkt: %d, pts: %lld dts: %lld\n", pkt.size, pkt.pts, pkt.dts);
av_free_packet(&pkt);
- if (switch_queue_size(context->eh.video_queue) > 300) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Dropping frames\n");
- av_frame_free(&vframe);
- continue;
- }
+ //if (switch_queue_size(context->eh.video_queue) > 300) {
+ // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Dropping frames\n");
+ // av_frame_free(&vframe);
+ // continue;
+ //}
if (got_data && error > 0) {
// switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "got picture %dx%d fmt: %d pktpts:%lld pktdts:%lld\n", vframe->width, vframe->height, vframe->format, vframe->pkt_pts, vframe->pkt_dts);
handle->pos = 0;
- switch_core_timer_init(&context->audio_timer, "soft", 1, 1, /*handle->samplerate / 1000,*/ context->pool);
- switch_core_timer_init(&context->video_timer, "soft", 1, 1, context->pool);
-
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Opening File [%s] %dhz %s\n",
file, handle->samplerate, switch_test_flag(handle, SWITCH_FILE_FLAG_VIDEO) ? " with VIDEO" : "");
switch_core_timer_destroy(&context->video_timer);
}
- if (context->audio_timer.interval) {
- switch_core_timer_destroy(&context->audio_timer);
- }
-
if (context->audio_buffer) {
switch_buffer_destroy(&context->audio_buffer);
}
return SWITCH_STATUS_FALSE;
}
-static void flush_video_queue(switch_queue_t *q)
+static void flush_video_queue(switch_queue_t *q, int min)
{
void *pop;
- if (switch_queue_size(q) == 0) {
+ if (switch_queue_size(q) <= min) {
return;
}
while (switch_queue_trypop(q, &pop) == SWITCH_STATUS_SUCCESS) {
switch_image_t *img = (switch_image_t *) pop;
switch_img_free(&img);
+ if (min && switch_queue_size(q) <= min) {
+ break;
+ }
+ }
+
+}
+
+static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, size_t *len)
+{
+
+ uint32_t datalen = 0;
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ // uint8_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }, *bp = buf;
+ // uint32_t encoded_rate;
+ av_file_context_t *context = (av_file_context_t *)handle->private_info;
+ // uint32_t size = 0;
+ uint32_t bytes;
+ int inuse;
+
+ if (!context->vid_ready) {
+ return status;
+ }
+
+ if (data && len) {
+ datalen = *len * 2 * handle->channels;
+
+ if (context->offset) {
+ char buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
+ switch_size_t samples = *len;
+ int fps = handle->samplerate / samples;
+ int lead_frames = (context->offset * fps) / 1000;
+
+ for (int x = 0; x < lead_frames; x++) {
+ switch_buffer_write(context->audio_buffer, buf, datalen);
+ }
+ context->offset = 0;
+ }
+
+ 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);
+ //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);
+
+ 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);
+ av_frame_make_writable(context->audio_st.tmp_frame);
+ switch_buffer_read(context->audio_buffer, context->audio_st.frame->data[0], bytes);
+ /* convert to destination format */
+ ret = avresample_convert(context->audio_st.resample_ctx,
+ (uint8_t **)context->audio_st.frame->data, 0, out_samples,
+ context->audio_st.tmp_frame->data, 0, context->audio_st.frame->nb_samples);
+
+ 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));
+ continue;
+ }
+
+ context->audio_st.tmp_frame->pts = context->audio_st.next_pts;
+ context->audio_st.next_pts += context->audio_st.frame->nb_samples;
+ ret = avcodec_encode_audio2(context->audio_st.st->codec, &pkt, context->audio_st.tmp_frame, &got_packet);
+ } else {
+ av_frame_make_writable(context->audio_st.frame);
+ switch_buffer_read(context->audio_buffer, context->audio_st.frame->data[0], bytes);
+ context->audio_st.frame->pts = context->audio_st.next_pts;
+ context->audio_st.next_pts += context->audio_st.frame->nb_samples;
+
+ ret = avcodec_encode_audio2(context->audio_st.st->codec, &pkt, context->audio_st.frame, &got_packet);
+ }
+
+ if (ret < 0) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error encoding audio frame: %d\n", ret);
+ continue;
+ }
+
+ if (got_packet) {
+ if (context->mutex) switch_mutex_lock(context->mutex);
+ ret = write_frame(context->fc, &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);
+ }
+ }
+ if (data) {
+ break;
+ }
}
+ return status;
}
static switch_status_t av_file_close(switch_file_handle_t *handle)
if (context->eh.video_thread) {
switch_thread_join(&status, context->eh.video_thread);
}
+
+ av_file_write(handle, NULL, NULL);
if (context->file_read_thread_running && context->file_read_thread) {
context->file_read_thread_running = 0;
}
if (context->eh.video_queue) {
- flush_video_queue(context->eh.video_queue);
+ flush_video_queue(context->eh.video_queue, 0);
}
if (context->fc) {
switch_core_timer_destroy(&context->video_timer);
}
- if (context->audio_timer.interval) {
- switch_core_timer_destroy(&context->audio_timer);
- }
-
switch_img_free(&context->last_img);
switch_buffer_destroy(&context->audio_buffer);
return *len == 0 ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
}
-static switch_status_t av_file_write(switch_file_handle_t *handle, void *data, size_t *len)
+static switch_status_t av_file_read_video(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
{
-
- uint32_t datalen = *len * 2 * handle->channels;
- switch_status_t status = SWITCH_STATUS_SUCCESS;
- // uint8_t buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = { 0 }, *bp = buf;
- // uint32_t encoded_rate;
av_file_context_t *context = (av_file_context_t *)handle->private_info;
- // uint32_t size = 0;
- uint32_t bytes;
- int inuse;
-
- if (!context->vid_ready) {
- return status;
- }
+ void *pop;
+ MediaStream *mst = &context->video_st;
+ AVStream *st = mst->st;
+ int ticks = 0;
+ int max_delta = 1 * AV_TIME_BASE; // 1 second
+ switch_status_t status = SWITCH_STATUS_SUCCESS;
+ double fl_to = 0.02;
+ int do_fl = 0;
- if (context->offset) {
- char buf[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
- switch_size_t samples = *len;
- int fps = handle->samplerate / samples;
- int lead_frames = (context->offset * fps) / 1000;
+ if (!context->has_video) return SWITCH_STATUS_FALSE;
- for (int x = 0; x < lead_frames; x++) {
- switch_buffer_write(context->audio_buffer, buf, datalen);
- }
- context->offset = 0;
+ if ((flags & SVR_CHECK)) {
+ return SWITCH_STATUS_BREAK;
}
- 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);
- //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);
-
- 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);
- av_frame_make_writable(context->audio_st.tmp_frame);
- switch_buffer_read(context->audio_buffer, context->audio_st.frame->data[0], bytes);
- /* convert to destination format */
- ret = avresample_convert(context->audio_st.resample_ctx,
- (uint8_t **)context->audio_st.frame->data, 0, out_samples,
- context->audio_st.tmp_frame->data, 0, context->audio_st.frame->nb_samples);
-
- 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));
- continue;
- }
-
- context->audio_st.tmp_frame->pts = context->audio_st.next_pts;
- context->audio_st.next_pts += context->audio_st.frame->nb_samples;
- ret = avcodec_encode_audio2(context->audio_st.st->codec, &pkt, context->audio_st.tmp_frame, &got_packet);
- } else {
- av_frame_make_writable(context->audio_st.frame);
- switch_buffer_read(context->audio_buffer, context->audio_st.frame->data[0], bytes);
-
- switch_core_timer_sync(&context->audio_timer);
- context->audio_st.frame->pts = context->audio_timer.samplecount;
- //context->audio_st.frame->pts = context->audio_st.next_pts;
- //context->audio_st.next_pts += context->audio_st.frame->nb_samples;
-
- ret = avcodec_encode_audio2(context->audio_st.st->codec, &pkt, context->audio_st.frame, &got_packet);
- }
-
- if (ret < 0) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Error encoding audio frame: %d\n", ret);
- continue;
- }
-
- if (got_packet) {
- if (context->mutex) switch_mutex_lock(context->mutex);
- ret = write_frame(context->fc, &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);
- }
- }
-
- break;
+ fl_to = (1000 / context->read_fps) * 1000;
+ //printf("WTF %d (%f)\n",switch_queue_size(context->eh.video_queue), fl_to);
+ if (flags & SVR_FLUSH) {
+ max_delta = fl_to * AV_TIME_BASE;
+ do_fl = 1;
}
+ if (context->last_img) {
+ if (mst->next_pts && (switch_time_now() - mst->next_pts > max_delta)) {
+ switch_img_free(&context->last_img); // too late
+ } else if (mst->next_pts && (switch_time_now() - mst->next_pts > -10000)) {
+ frame->img = context->last_img;
+ context->last_img = NULL;
+ return SWITCH_STATUS_SUCCESS;
+ }
-
-end:
- return status;
-}
-
-
-static switch_status_t av_file_read_video(switch_file_handle_t *handle, switch_frame_t *frame, switch_video_read_flag_t flags)
-{
- void *pop;
- av_file_context_t *context = (av_file_context_t *)handle->private_info;
- switch_status_t status;
- int fps = (int)ceil(handle->mm.fps);
- int min_qsize = context->read_fps;
-
- if (fps && fps < min_qsize) {
- min_qsize = fps;
+ if (!(flags & SVR_BLOCK) && !do_fl) return SWITCH_STATUS_BREAK;
}
- if (!min_qsize) {
- min_qsize = 1;
- }
-
- if (!context->file_read_thread_running) {
+ if (!context->file_read_thread_running && switch_queue_size(context->eh.video_queue) == 0) {
return SWITCH_STATUS_FALSE;
}
- if ((flags & SVR_CHECK)) {
- return SWITCH_STATUS_BREAK;
+ if (st->codec->time_base.num) {
+ ticks = st->parser ? st->parser->repeat_pict + 1 : st->codec->ticks_per_frame;
+ // mst->next_pts += ((int64_t)AV_TIME_BASE * st->codec->time_base.num * ticks) / st->codec->time_base.den;
}
- if (switch_queue_size(context->eh.video_queue) < min_qsize / 2) {
- return SWITCH_STATUS_BREAK;
- }
-
- while((flags & SVR_FLUSH) && switch_queue_size(context->eh.video_queue) > min_qsize) {
- if (switch_queue_trypop(context->eh.video_queue, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_image_t *img = (switch_image_t *) pop;
- switch_img_free(&img);
- }
+ if (!context->video_start_time) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "start: %" SWITCH_INT64_T_FMT " ticks: %d ticks_per_frame: %d st num:%d st den:%d codec num:%d codec den:%d start: %" SWITCH_TIME_T_FMT ", duration:%" SWITCH_INT64_T_FMT " nb_frames:%" SWITCH_INT64_T_FMT " q2d:%f\n",
+ context->video_start_time, ticks, st->codec->ticks_per_frame, st->time_base.num, st->time_base.den, st->codec->time_base.num, st->codec->time_base.den,
+ st->start_time, st->duration, st->nb_frames, av_q2d(st->time_base));
}
- if (!context->file_read_thread_running) {
- return SWITCH_STATUS_FALSE;
- }
+ again:
if ((flags & SVR_BLOCK)) {
status = switch_queue_pop(context->eh.video_queue, &pop);
status = switch_queue_trypop(context->eh.video_queue, &pop);
}
- if (status == SWITCH_STATUS_SUCCESS) {
- if (!pop) {
- return SWITCH_STATUS_FALSE;
+ if (pop && status == SWITCH_STATUS_SUCCESS) {
+ switch_image_t *img = (switch_image_t *)pop;
+ uint64_t pts;
+ uint64_t now = switch_time_now();
+
+ pts = av_rescale_q(*((uint64_t *)img->user_priv), st->time_base, AV_TIME_BASE_Q);
+
+ if (!context->video_start_time) {
+ context->video_start_time = now - pts;
}
- frame->img = (switch_image_t *) pop;
- return SWITCH_STATUS_SUCCESS;
+ if (st->time_base.num == 0) {
+ mst->next_pts = 0;
+ } else {
+ //uint64_t last_pts = mst->next_pts;
+ mst->next_pts = context->video_start_time + pts;
+ //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "pts: %" SWITCH_INT64_T_FMT " last_pts: %" SWITCH_INT64_T_FMT " delta: %" SWITCH_INT64_T_FMT " frame_pts: %" SWITCH_INT64_T_FMT " nextpts: %" SWITCH_INT64_T_FMT ", num: %d, den:%d num:%d den:%d sleep: %" SWITCH_INT64_T_FMT "\n",
+ //pts, last_pts, mst->next_pts - last_pts, *((uint64_t *)img->user_priv), mst->next_pts, st->time_base.num, st->time_base.den, st->codec->time_base.num, st->codec->time_base.den, mst->next_pts - now);
+ }
+
+ if (pts == 0) mst->next_pts = 0;
+
+ if ((mst->next_pts && switch_time_now() - mst->next_pts > max_delta)) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG3, "picture is too late, off: %" SWITCH_INT64_T_FMT " queue size:%u\n", (int64_t)(switch_time_now() - mst->next_pts), switch_queue_size(context->eh.video_queue));
+ switch_img_free(&img);
+ max_delta = AV_TIME_BASE;
+
+ if (switch_queue_size(context->eh.video_queue) > 0) {
+ goto again;
+ } else if (!(flags & SVR_BLOCK) && !do_fl) {
+ mst->next_pts = 0;
+ return SWITCH_STATUS_BREAK;
+ }
+ }
+
+ if ((flags & SVR_BLOCK) || do_fl) {
+ while (switch_micro_time_now() - mst->next_pts < -10000 / 2) {
+ // switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "yield\n");
+ switch_yield(10000);
+ }
+ frame->img = img;
+ do_fl = 0;
+ } else {
+ if (switch_micro_time_now() - mst->next_pts > -10000 / 2) {
+ frame->img = img;
+ } else {
+ context->last_img = img;
+ return SWITCH_STATUS_BREAK;
+ }
+ }
+
+ } else {
+ return SWITCH_STATUS_BREAK;
}
- return (flags & SVR_FLUSH) ? SWITCH_STATUS_BREAK : status;
+ return frame->img ? SWITCH_STATUS_SUCCESS : SWITCH_STATUS_FALSE;
}
static switch_status_t av_file_write_video(switch_file_handle_t *handle, switch_frame_t *frame)
context->eh.fc = context->fc;
context->eh.mm = &handle->mm;
context->eh.timer = &context->video_timer;
- context->eh.other_timer = &context->audio_timer;
switch_queue_create(&context->eh.video_queue, SWITCH_CORE_QUEUE_LEN, handle->memory_pool);
switch_threadattr_create(&thd_attr, handle->memory_pool);
//switch_threadattr_priority_set(thd_attr, SWITCH_PRI_REALTIME);
switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE);
switch_thread_create(&context->eh.video_thread, thd_attr, video_thread_run, &context->eh, handle->memory_pool);
+ switch_core_timer_init(&context->video_timer, "soft", 1, 1, context->pool);
+ switch_buffer_zero(context->audio_buffer);
+ context->audio_st.frame->pts = 0;
+ context->audio_st.next_pts = 0;
}
if (context->has_video) {
return status;
}
+
static switch_status_t av_file_set_string(switch_file_handle_t *handle, switch_audio_col_t col, const char *string)
{
av_file_context_t *context = (av_file_context_t *)handle->private_info;
int last_h;
int serno;
int pop_count;
- int video_sync;
switch_image_t *banner_img;
switch_time_t banner_timeout;
struct local_stream_context *next;
char *timer_name;
local_stream_context_t *context_list;
int total;
+ int first;
switch_dir_t *dir_handle;
switch_mutex_t *mutex;
switch_memory_pool_t *pool;
switch_memory_pool_t *temp_pool = NULL;
uint32_t dir_count = 0, do_shuffle = 0;
char *p;
- int old_total = 0;
switch_mutex_lock(globals.mutex);
THREADS++;
is_open = switch_test_flag(use_fh, SWITCH_FILE_OPEN);
- if (is_open && source->total != old_total && source->total == 1) {
- if (switch_core_file_has_video(&fh)) {
- flush_video_queue(source->video_q);
- }
-
- switch_buffer_zero(audio_buffer);
- }
-
- old_total = source->total;
-
if (source->hup) {
source->hup = 0;
if (is_open) {
}
if (is_open) {
+ int svr = 0;
+
if (switch_core_has_video() && switch_core_file_has_video(use_fh)) {
switch_frame_t vid_frame = { 0 };
if (use_fh == &source->chime_fh && switch_core_file_has_video(&fh)) {
- if (switch_core_file_read_video(&fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
+ if (switch_core_file_read_video(&fh, &vid_frame, svr) == SWITCH_STATUS_SUCCESS) {
switch_img_free(&vid_frame.img);
}
}
- if (switch_core_file_read_video(use_fh, &vid_frame, SVR_FLUSH) == SWITCH_STATUS_SUCCESS) {
+ while (switch_core_file_read_video(use_fh, &vid_frame, svr) == SWITCH_STATUS_SUCCESS) {
if (vid_frame.img) {
int flush = 1;
source->has_video = 1;
-
if (source->total) {
if (switch_queue_trypush(source->video_q, vid_frame.img) == SWITCH_STATUS_SUCCESS) {
flush = 0;
break;
}
- source->prebuf = source->samples * 2 * source->channels * 10;
-
- if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
- void *pop;
+ source->prebuf = source->samples * 2 * source->channels;
+ if (!source->total) {
+ flush_video_queue(source->video_q);
+ switch_buffer_zero(audio_buffer);
+ } else if (used > source->samples * 2 * source->channels) {
+ //if (!is_open || used >= source->prebuf || (source->total && used > source->samples * 2 * source->channels)) {
+ void *pop;
+ uint32_t bused;
+
used = switch_buffer_read(audio_buffer, dist_buf, source->samples * 2 * source->channels);
- if (!source->total) {
- flush_video_queue(source->video_q);
- } else {
- uint32_t bused = 0;
+ bused = 0;
- switch_mutex_lock(source->mutex);
- for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
+ switch_mutex_lock(source->mutex);
+ for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
- if (source->has_video) {
- switch_set_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
- } else {
- switch_clear_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
- }
+ if (source->has_video) {
+ switch_set_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
+ } else {
+ switch_clear_flag(cp->handle, SWITCH_FILE_FLAG_VIDEO);
+ }
- if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
- continue;
- }
+ if (switch_test_flag(cp->handle, SWITCH_FILE_CALLBACK)) {
+ continue;
+ }
- switch_mutex_lock(cp->audio_mutex);
- bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer);
- if (bused > source->samples * 768) {
- switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n",
- cp->func, cp->file, cp->line, bused, (long)source->samples);
- switch_buffer_zero(cp->audio_buffer);
- } else {
- switch_buffer_write(cp->audio_buffer, dist_buf, used);
- }
- switch_mutex_unlock(cp->audio_mutex);
+ switch_mutex_lock(cp->audio_mutex);
+ bused = (uint32_t)switch_buffer_inuse(cp->audio_buffer);
+ if (bused > source->samples * 768) {
+ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Flushing Stream Handle Buffer [%s() %s:%d] size: %u samples: %ld\n",
+ cp->func, cp->file, cp->line, bused, (long)source->samples);
+ switch_buffer_zero(cp->audio_buffer);
+ } else {
+ switch_buffer_write(cp->audio_buffer, dist_buf, used);
}
- switch_mutex_unlock(source->mutex);
+ switch_mutex_unlock(cp->audio_mutex);
+ }
+ switch_mutex_unlock(source->mutex);
- while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
- switch_image_t *img = (switch_image_t *) pop;
- switch_image_t *imgcp = NULL;
-
- if (source->total == 1) {
- switch_queue_push(source->context_list->video_q, img);
- } else {
- if (source->context_list) {
- switch_mutex_lock(source->mutex);
- for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
- if (cp->video_q) {
- imgcp = NULL;
- switch_img_copy(img, &imgcp);
- if (imgcp) {
- if (switch_queue_trypush(cp->video_q, imgcp) != SWITCH_STATUS_SUCCESS) {
- flush_video_queue(cp->video_q);
- }
+ while (switch_queue_trypop(source->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
+ switch_image_t *img = (switch_image_t *) pop;
+ switch_image_t *imgcp = NULL;
+
+ if (source->total == 1) {
+ switch_queue_push(source->context_list->video_q, img);
+ } else {
+ if (source->context_list) {
+ switch_mutex_lock(source->mutex);
+ for (cp = source->context_list; cp && RUNNING; cp = cp->next) {
+ if (cp->video_q) {
+ imgcp = NULL;
+ switch_img_copy(img, &imgcp);
+ if (imgcp) {
+ if (switch_queue_trypush(cp->video_q, imgcp) != SWITCH_STATUS_SUCCESS) {
+ flush_video_queue(cp->video_q);
}
}
}
- switch_mutex_unlock(source->mutex);
}
- switch_img_free(&img);
+ switch_mutex_unlock(source->mutex);
}
+ switch_img_free(&img);
}
}
}
context->next = source->context_list;
source->context_list = context;
source->total++;
+ if (source->total == 1) {
+ source->first = 1;
+ }
switch_mutex_unlock(source->mutex);
end:
return SWITCH_STATUS_BREAK;
}
- context->video_sync = 1;
-
- while(context->ready && context->source->ready && (flags & SVR_FLUSH) && switch_queue_size(context->video_q) > min_qsize) {
+ while(context->ready && context->source->ready && (flags & SVR_FLUSH) && switch_queue_size(context->video_q) > min_qsize / 2) {
if (switch_queue_trypop(context->video_q, &pop) == SWITCH_STATUS_SUCCESS) {
switch_image_t *img = (switch_image_t *) pop;
switch_img_free(&img);
return SWITCH_STATUS_FALSE;
}
+ while (switch_queue_size(context->video_q) < 5) {
+ return SWITCH_STATUS_BREAK;
+ }
+
if ((flags & SVR_BLOCK)) {
status = switch_queue_pop(context->video_q, &pop);
} else {
//switch_img_overlay(frame->img, context->banner_img, 0, frame->img->d_h - context->banner_img->d_h, 100);
switch_img_patch(frame->img, context->banner_img, 0, frame->img->d_h - context->banner_img->d_h);
}
-
+
return SWITCH_STATUS_SUCCESS;
}