#define INT64_MAX 9223372036854775807LL
#endif
#define MAX_RETRY 1000
+// max pts/curr_pos drift allowed before correction (in seconds)
+#define AUDIO_PTS_TOLERANCE 0.04
#include "asset.h"
#include "bccmodels.h"
#include "mwindow.h"
#include "vframe.h"
+#ifdef FFMPEG3
+#define url filename
+#else
+#define av_register_all(s)
+#define avfilter_register_all(s)
+#endif
#define VIDEO_INBUF_SIZE 0x10000
#define AUDIO_INBUF_SIZE 0x10000
int FFAudioStream::decode_frame(AVFrame *frame)
{
int first_frame = seeked; seeked = 0;
+ frame->best_effort_timestamp = AV_NOPTS_VALUE;
int ret = avcodec_receive_frame(avctx, frame);
if( ret < 0 ) {
if( first_frame || ret == AVERROR(EAGAIN) ) return 0;
return -1;
}
int64_t pkt_ts = frame->best_effort_timestamp;
- if( pkt_ts != AV_NOPTS_VALUE )
- curr_pos = ffmpeg->to_secs(pkt_ts - nudge, st->time_base) * sample_rate + 0.5;
+ if( pkt_ts != AV_NOPTS_VALUE ) {
+ double ts = ffmpeg->to_secs(pkt_ts - nudge, st->time_base);
+ double t = (double)curr_pos / sample_rate;
+// some time_base clocks are very grainy, too grainy for audio (clicks, pops)
+ if( fabs(ts - t) > AUDIO_PTS_TOLERANCE )
+ curr_pos = ts * sample_rate + 0.5;
+ }
return 1;
}
if( pos == curr_pos ) return 0;
reset_history(); mbsz = 0;
// guarentee preload > 1sec samples
- if( seek(pos-sample_rate, sample_rate) < 0 ) return -1;
+ if( (pos-=sample_rate) < 0 ) pos = 0;
+ if( seek(pos, sample_rate) < 0 ) return -1;
return 1;
}
case BC_YUV422P:
usz /= 2;
case BC_YUV444P:
+ case BC_GBRP:
// override av_image_fill_arrays() for planar types
ipic->data[0] = frame->get_y(); ipic->linesize[0] = ysz;
ipic->data[1] = frame->get_u(); ipic->linesize[1] = usz;
case BC_YUV422P:
usz /= 2;
case BC_YUV444P:
+ case BC_GBRP:
// override av_image_fill_arrays() for planar types
opic->data[0] = frame->get_y(); opic->linesize[0] = ysz;
opic->data[1] = frame->get_u(); opic->linesize[1] = usz;
int FFMPEG::init_decoder(const char *filename)
{
ff_lock("FFMPEG::init_decoder");
+ av_register_all();
char file_opts[BCTEXTLEN];
char *bp = strrchr(strcpy(file_opts, filename), '/');
char *sp = strrchr(!bp ? file_opts : bp, '.');
return 1;
}
ff_lock("FFMPEG::init_encoder");
+ av_register_all();
char format[BCSTRLEN];
if( get_format(format, "format", file_format) )
strcpy(format, file_format);
return 1;
}
+#ifdef HAVE_DV
if( !strcmp(codec_name, CODEC_TAG_DVSD) ) strcpy(codec_name, "dv");
+#endif
else if( !strcmp(codec_name, CODEC_TAG_MJPEG) ) strcpy(codec_name, "mjpeg");
else if( !strcmp(codec_name, CODEC_TAG_JPEG) ) strcpy(codec_name, "jpeg");
int FFVideoStream::create_filter(const char *filter_spec, AVCodecParameters *avpar)
{
+ avfilter_register_all();
const char *sp = filter_spec;
char filter_name[BCSTRLEN], *np = filter_name;
int i = sizeof(filter_name);
int FFAudioStream::create_filter(const char *filter_spec, AVCodecParameters *avpar)
{
+ avfilter_register_all();
const char *sp = filter_spec;
char filter_name[BCSTRLEN], *np = filter_name;
int i = sizeof(filter_name);
if( !frame ) {
fprintf(stderr,"FFMPEG::scan: ");
fprintf(stderr,_("av_frame_alloc failed\n"));
+ fprintf(stderr,"FFMPEG::scan:file=%s\n", file_base->asset->path);
return -1;
}
}
fprintf(stderr,"FFMPEG::scan: ");
fprintf(stderr,_("codec open failed\n"));
+ fprintf(stderr,"FFMPEG::scan:file=%s\n", file_base->asset->path);
avcodec_free_context(&avctx);
}