FS-8750 implement file_seek for video files
This commit is contained in:
parent
10b46424f3
commit
5ca9dea684
|
@ -1245,6 +1245,7 @@ struct av_file_context {
|
||||||
switch_image_t *last_img;
|
switch_image_t *last_img;
|
||||||
int read_fps;
|
int read_fps;
|
||||||
switch_time_t last_vid_push;
|
switch_time_t last_vid_push;
|
||||||
|
int64_t seek_ts;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct av_file_context av_file_context_t;
|
typedef struct av_file_context av_file_context_t;
|
||||||
|
@ -1277,6 +1278,9 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
|
||||||
switch_goto_status(SWITCH_STATUS_FALSE, err);
|
switch_goto_status(SWITCH_STATUS_FALSE, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle->seekable = context->fc->iformat->read_seek2 ? 1 : (context->fc->iformat->read_seek ? 1 : 0);
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "file %s is %sseekable\n", filename, handle->seekable ? "" : "not ");
|
||||||
|
|
||||||
/** Get information on the input file (number of streams etc.). */
|
/** Get information on the input file (number of streams etc.). */
|
||||||
if ((error = avformat_find_stream_info(context->fc, NULL)) < 0) {
|
if ((error = avformat_find_stream_info(context->fc, NULL)) < 0) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open find stream info (error '%s')\n", get_error_text(error));
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Could not open find stream info (error '%s')\n", get_error_text(error));
|
||||||
|
@ -1346,14 +1350,18 @@ static switch_status_t open_input_file(av_file_context_t *context, switch_file_h
|
||||||
av_opt_set_int(resample_ctx, "in_channel_count", c->channels, 0);
|
av_opt_set_int(resample_ctx, "in_channel_count", c->channels, 0);
|
||||||
av_opt_set_int(resample_ctx, "in_sample_rate", c->sample_rate, 0);
|
av_opt_set_int(resample_ctx, "in_sample_rate", c->sample_rate, 0);
|
||||||
av_opt_set_int(resample_ctx, "in_sample_fmt", c->sample_fmt, 0);
|
av_opt_set_int(resample_ctx, "in_sample_fmt", c->sample_fmt, 0);
|
||||||
av_opt_set_int(resample_ctx, "in_channel_layout", c->channel_layout, 0);
|
av_opt_set_int(resample_ctx, "in_channel_layout",
|
||||||
|
(c->channel_layout == 0 && c->channels == 2) ? AV_CH_LAYOUT_STEREO : c->channel_layout, 0);
|
||||||
av_opt_set_int(resample_ctx, "out_channel_count", handle->channels, 0);
|
av_opt_set_int(resample_ctx, "out_channel_count", handle->channels, 0);
|
||||||
av_opt_set_int(resample_ctx, "out_sample_rate", handle->samplerate,0);
|
av_opt_set_int(resample_ctx, "out_sample_rate", handle->samplerate,0);
|
||||||
av_opt_set_int(resample_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
av_opt_set_int(resample_ctx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
||||||
av_opt_set_int(resample_ctx, "out_channel_layout", handle->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO, 0);
|
av_opt_set_int(resample_ctx, "out_channel_layout", handle->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO, 0);
|
||||||
|
|
||||||
if ((ret = avresample_open(resample_ctx)) < 0) {
|
if ((ret = avresample_open(resample_ctx)) < 0) {
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the resampling context\n");
|
char errbuf[1024];
|
||||||
|
av_strerror(ret, errbuf, 1024);
|
||||||
|
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to initialize the resampling context, ret=%d: %s\n", ret, errbuf);
|
||||||
av_free(resample_ctx);
|
av_free(resample_ctx);
|
||||||
switch_goto_status(SWITCH_STATUS_FALSE, err);
|
switch_goto_status(SWITCH_STATUS_FALSE, err);
|
||||||
}
|
}
|
||||||
|
@ -1392,6 +1400,28 @@ static void *SWITCH_THREAD_FUNC file_read_thread_run(switch_thread_t *thread, vo
|
||||||
while (context->file_read_thread_running && !context->closed) {
|
while (context->file_read_thread_running && !context->closed) {
|
||||||
int vid_frames = 0;
|
int vid_frames = 0;
|
||||||
|
|
||||||
|
if (context->seek_ts >= 0) {
|
||||||
|
int ret = 0;
|
||||||
|
int stream_id = -1;
|
||||||
|
|
||||||
|
switch_mutex_lock(context->mutex);
|
||||||
|
switch_buffer_zero(context->audio_buffer);
|
||||||
|
switch_mutex_unlock(context->mutex);
|
||||||
|
|
||||||
|
if (context->eh.video_queue) {
|
||||||
|
flush_video_queue(context->eh.video_queue, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (context->has_audio) stream_id = context->audio_st.st->index;
|
||||||
|
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "seeking to %" SWITCH_INT64_T_FMT "\n", context->seek_ts);
|
||||||
|
ret = avformat_seek_file(context->fc, stream_id, 0, context->seek_ts, INT64_MAX, 0);
|
||||||
|
context->seek_ts = -1;
|
||||||
|
context->video_st.next_pts = 0;
|
||||||
|
context->video_start_time = 0;
|
||||||
|
|
||||||
|
avcodec_flush_buffers(context->video_st.st->codec);
|
||||||
|
}
|
||||||
|
|
||||||
if (context->has_video) {
|
if (context->has_video) {
|
||||||
vid_frames = switch_queue_size(context->eh.video_queue);
|
vid_frames = switch_queue_size(context->eh.video_queue);
|
||||||
}
|
}
|
||||||
|
@ -1495,7 +1525,7 @@ again:
|
||||||
|
|
||||||
img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, vframe->width, vframe->height, 1);
|
img = switch_img_alloc(NULL, SWITCH_IMG_FMT_I420, vframe->width, vframe->height, 1);
|
||||||
if (img) {
|
if (img) {
|
||||||
uint64_t *pts = malloc(sizeof(uint64_t));
|
int64_t *pts = malloc(sizeof(int64_t));
|
||||||
|
|
||||||
if (pts) {
|
if (pts) {
|
||||||
#ifdef ALT_WAY
|
#ifdef ALT_WAY
|
||||||
|
@ -1624,7 +1654,7 @@ static switch_status_t av_file_open(switch_file_handle_t *handle, const char *pa
|
||||||
memset(context, 0, sizeof(av_file_context_t));
|
memset(context, 0, sizeof(av_file_context_t));
|
||||||
handle->private_info = context;
|
handle->private_info = context;
|
||||||
context->pool = handle->memory_pool;
|
context->pool = handle->memory_pool;
|
||||||
|
context->seek_ts = -1;
|
||||||
context->offset = DFT_RECORD_OFFSET;
|
context->offset = DFT_RECORD_OFFSET;
|
||||||
if (handle->params && (tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
|
if (handle->params && (tmp = switch_event_get_header(handle->params, "av_video_offset"))) {
|
||||||
context->offset = atoi(tmp);
|
context->offset = atoi(tmp);
|
||||||
|
@ -1970,7 +2000,15 @@ static switch_status_t av_file_close(switch_file_handle_t *handle)
|
||||||
|
|
||||||
static switch_status_t av_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
|
static switch_status_t av_file_seek(switch_file_handle_t *handle, unsigned int *cur_sample, int64_t samples, int whence)
|
||||||
{
|
{
|
||||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "seek not implemented\n");
|
av_file_context_t *context = (av_file_context_t *)handle->private_info;
|
||||||
|
|
||||||
|
if (whence == SEEK_SET) {
|
||||||
|
handle->pos = handle->offset_pos = samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->seek_ts = samples / handle->native_rate * AV_TIME_BASE;
|
||||||
|
*cur_sample = context->seek_ts;
|
||||||
|
|
||||||
return SWITCH_STATUS_FALSE;
|
return SWITCH_STATUS_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue