]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-8240 #comment please test
authorAnthony Minessale <anthm@freeswitch.org>
Thu, 1 Oct 2015 03:00:39 +0000 (22:00 -0500)
committerAnthony Minessale <anthm@freeswitch.org>
Thu, 1 Oct 2015 03:00:47 +0000 (22:00 -0500)
src/mod/applications/mod_av/avformat.c
src/mod/applications/mod_conference/conference_video.c
src/mod/formats/mod_local_stream/mod_local_stream.c
src/switch_core_media.c
src/switch_ivr_async.c

index ab3fc2b9ce25bf5e84fc70885c4d0a8787a5b76a..d33c4626666aea84f44f23e4751ccba6c43ba661 100644 (file)
@@ -139,7 +139,6 @@ typedef struct record_helper_s {
        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;
@@ -259,11 +258,6 @@ static switch_status_t add_stream(MediaStream *mst, AVFormatContext *fc, AVCodec
                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;
@@ -500,59 +494,37 @@ static switch_status_t open_audio(AVFormatContext *fc, AVCodec *codec, MediaStre
 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;
@@ -568,14 +540,6 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
                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++;
@@ -606,8 +570,6 @@ static void *SWITCH_THREAD_FUNC video_thread_run(switch_thread_t *thread, void *
 
  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;
@@ -630,7 +592,7 @@ static switch_status_t video_read_callback(switch_core_session_t *session, switc
                switch_queue_push(eh->video_queue, img);
        }
 
-       return SWITCH_STATUS_SUCCESS;;
+       return SWITCH_STATUS_SUCCESS;
 }
 
 static void close_stream(AVFormatContext *fc, MediaStream *mst)
@@ -1093,7 +1055,6 @@ struct av_file_context {
        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;
@@ -1250,17 +1211,18 @@ static void *SWITCH_THREAD_FUNC file_read_thread_run(switch_thread_t *thread, vo
        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;
@@ -1276,7 +1238,10 @@ static void *SWITCH_THREAD_FUNC file_read_thread_run(switch_thread_t *thread, vo
                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) {
@@ -1289,11 +1254,11 @@ static void *SWITCH_THREAD_FUNC file_read_thread_run(switch_thread_t *thread, vo
                        // 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);
@@ -1584,9 +1549,6 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
        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" : "");
 
@@ -1602,10 +1564,6 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
                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);
        }
@@ -1618,19 +1576,121 @@ static switch_status_t av_file_truncate(switch_file_handle_t *handle, int64_t of
        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)
@@ -1645,6 +1705,8 @@ 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;
@@ -1652,7 +1714,7 @@ static switch_status_t av_file_close(switch_file_handle_t *handle)
        }
 
        if (context->eh.video_queue) {
-               flush_video_queue(context->eh.video_queue);
+               flush_video_queue(context->eh.video_queue, 0);
        }
 
        if (context->fc) {
@@ -1665,10 +1727,6 @@ static switch_status_t av_file_close(switch_file_handle_t *handle)
                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);
@@ -1722,142 +1780,59 @@ static switch_status_t av_file_read(switch_file_handle_t *handle, void *data, si
        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);
@@ -1865,16 +1840,62 @@ static switch_status_t av_file_read_video(switch_file_handle_t *handle, switch_f
                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)
@@ -1923,13 +1944,16 @@ static switch_status_t av_file_write_video(switch_file_handle_t *handle, switch_
                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) {
@@ -1945,6 +1969,7 @@ end:
        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;
index 07c9a1021d9a38b0b68e5656927fa87aaca64e99..6935e61cd86664daca905f3652faabbfd5ff71e2 100644 (file)
@@ -1493,9 +1493,7 @@ void *SWITCH_THREAD_FUNC conference_video_muxing_write_thread_run(switch_thread_
                                        if (last) {
                                                int delta = now - last;
                                                if (delta > member->conference->video_fps.ms * 5000) {
-                                                       printf("WTF %d %d\n", delta, member->conference->video_fps.ms * 5000);
-                                                       switch_core_session_request_video_refresh(member->session);
-                                                       
+                                                       switch_core_session_request_video_refresh(member->session);                                                     
                                                }
                                        }
 
index 27542a08e832d4b0e188cb969415b1e9638842a7..69986b27cb25048864a88738658ce45398547cb1 100644 (file)
@@ -70,7 +70,6 @@ struct local_stream_context {
        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;
@@ -90,6 +89,7 @@ struct local_stream_source {
        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;
@@ -161,7 +161,6 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
        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++;
@@ -364,16 +363,6 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
 
                                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) {
@@ -391,21 +380,22 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
                                }
                                
                                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;
@@ -465,69 +455,70 @@ static void *SWITCH_THREAD_FUNC read_stream_thread(switch_thread_t *thread, void
                                        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);
                                                }
                                        }
                                }
@@ -725,6 +716,9 @@ static switch_status_t local_stream_file_open(switch_file_handle_t *handle, cons
        context->next = source->context_list;
        source->context_list = context;
        source->total++;
+       if (source->total == 1) {
+               source->first = 1;
+       }
        switch_mutex_unlock(source->mutex);
 
   end:
@@ -814,9 +808,7 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
                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);
@@ -827,6 +819,10 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
                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 {
@@ -889,7 +885,7 @@ static switch_status_t local_stream_file_read_video(switch_file_handle_t *handle
                //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;
 }
 
index 6ba192e186d6cffd3c934a9cb50b17c09f89a487..edcd43a9b2af102ea52e120d43e09d93ed2b6e98 100644 (file)
@@ -5120,9 +5120,9 @@ static void *SWITCH_THREAD_FUNC video_helper_thread(switch_thread_t *thread, voi
                if (switch_channel_test_flag(channel, CF_VIDEO_READY)) {
                        switch_mutex_lock(mh->file_mutex);
                        if (smh->video_write_fh && switch_channel_ready(session->channel) && switch_test_flag(smh->video_write_fh, SWITCH_FILE_OPEN)) {
-                               switch_status_t wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, SVR_FLUSH);
+                               switch_status_t wstatus = switch_core_file_read_video(smh->video_write_fh, &fr, 0);
                                if (wstatus == SWITCH_STATUS_SUCCESS) {
-                                       switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_NONE, 0);
+                                       switch_core_session_write_video_frame(session, &fr, SWITCH_IO_FLAG_NONE, SVR_FLUSH);
                                        switch_img_free(&fr.img);
                                } else if (wstatus != SWITCH_STATUS_BREAK && wstatus != SWITCH_STATUS_IGNORE) {
                                        smh->video_write_fh = NULL;
index 9f5b472b19e133854183812353b429f3a49bcc33..d55b8ac29bab237e57089159dff843e765b1098f 100644 (file)
@@ -1113,11 +1113,14 @@ static void *SWITCH_THREAD_FUNC recording_thread(switch_thread_t *thread, void *
        switch_size_t bsize = SWITCH_RECOMMENDED_BUFFER_SIZE, samples = 0, inuse = 0;
        unsigned char *data;
        int channels = 1;
+       switch_codec_implementation_t read_impl = { 0 };
 
        if (switch_core_session_read_lock(session) != SWITCH_STATUS_SUCCESS) {
                return NULL;
        }
 
+       switch_core_session_get_read_impl(session, &read_impl);
+       bsize = read_impl.decoded_bytes_per_packet;
        rh = switch_core_media_bug_get_user_data(bug);
        switch_buffer_create_dynamic(&rh->thread_buffer, 1024 * 512, 1024 * 64, 0);
        rh->thread_ready = 1;