{
inp = outp = bfr;
hpos = 0;
+ memset(bfr, 0, lmt-bfr);
}
void FFAudioStream::iseek(int64_t ofs)
{
+ if( ofs > hpos ) ofs = hpos;
+ if( ofs > sz ) ofs = sz;
outp = inp - ofs*nch;
if( outp < bfr ) outp += sz*nch;
}
ret = AVERROR(ENOMEM);
}
if( ret >= 0 ) {
+ av_codec_set_pkt_timebase(avctx, st->time_base);
+ if( decoder->capabilities & AV_CODEC_CAP_DR1 )
+ avctx->flags |= CODEC_FLAG_EMU_EDGE;
avcodec_parameters_to_context(avctx, st->codecpar);
ret = avcodec_open2(avctx, decoder, &copts);
}
- if( ret >= 0 )
+ if( ret >= 0 ) {
reading = 1;
+ }
else
eprintf(_("open decoder failed\n"));
}
npkts = MAX_RETRY;
}
}
+ if( pos == curr_pos ) return 0;
if( pos > 0 && st->time_base.num > 0 ) {
double secs = pos / rate;
tstmp = secs * st->time_base.den / st->time_base.num;
}
int ret = avformat_seek_file(fmt_ctx, st->index, -INT64_MAX, seek, INT64_MAX, flags);
#else
- int ret = av_seek_frame(fmt_ctx, st->index, tstmp, AVSEEK_FLAG_ANY);
+ int ret = av_seek_frame(fmt_ctx, st->index, tstmp, AVSEEK_FLAG_ANY);
#endif
int retry = MAX_RETRY;
while( ret >= 0 ) {
}
}
if( ret < 0 ) {
-//printf("** seek fail %ld, %ld\n", pos, tstmp);
+printf("** seek fail %ld, %ld\n", pos, tstmp);
seeked = need_packet = 0;
st_eof(flushed=1);
return -1;
mbsz = 0;
length = 0;
resample_context = 0;
+ swr_ichs = swr_ifmt = swr_irate = 0;
aud_bfr_sz = 0;
aud_bfr = 0;
delete [] bfr;
}
+void FFAudioStream::init_swr(int ichs, int ifmt, int irate)
+{
+ if( resample_context ) {
+ if( swr_ichs == ichs && swr_ifmt == ifmt && swr_irate == irate )
+ return;
+ swr_free(&resample_context);
+ }
+ swr_ichs = ichs; swr_ifmt = ifmt; swr_irate = irate;
+ if( ichs == channels && ifmt == AV_SAMPLE_FMT_FLT && irate == sample_rate )
+ return;
+ uint64_t ilayout = av_get_default_channel_layout(ichs);
+ if( !ilayout ) ilayout = ((uint64_t)1<<ichs) - 1;
+ uint64_t olayout = av_get_default_channel_layout(channels);
+ if( !olayout ) olayout = ((uint64_t)1<<channels) - 1;
+ resample_context = swr_alloc_set_opts(NULL,
+ olayout, AV_SAMPLE_FMT_FLT, sample_rate,
+ ilayout, (AVSampleFormat)ifmt, irate,
+ 0, NULL);
+ if( resample_context )
+ swr_init(resample_context);
+}
+
int FFAudioStream::get_samples(float *&samples, uint8_t **data, int len)
{
samples = *(float **)data;
for( int i=0; ret>=0 && !flushed && curr_pos<end_pos && i<MAX_RETRY; ++i ) {
ret = read_frame(frame);
if( ret > 0 ) {
+ init_swr(frame->channels, frame->format, frame->sample_rate);
load_history(&frame->extended_data[0], frame->nb_samples);
curr_pos += frame->nb_samples;
}
int FFAudioStream::audio_seek(int64_t pos)
{
- if( decode_activate() < 0 ) return -1;
+ if( decode_activate() <= 0 ) return -1;
if( !st->codecpar ) return -1;
if( in_history(pos) ) return 0;
if( pos == curr_pos ) return 0;
if( encode_activate() <= 0 ) return -1;
ffmpeg->flow_ctl();
int ret = 0;
- int64_t count = load_buffer(samples, len);
+ int64_t count = samples ? load_buffer(samples, len) : used();
+ int frame_sz1 = samples ? frame_sz-1 : 0;
FFrame *frm = 0;
- while( ret >= 0 && count >= frame_sz ) {
+ while( ret >= 0 && count > frame_sz1 ) {
frm = new FFrame(this);
if( (ret=frm->initted()) < 0 ) break;
AVFrame *frame = *frm;
- float *bfrp = get_outp(frame_sz);
+ len = count >= frame_sz ? frame_sz : count;
+ float *bfrp = get_outp(len);
ret = swr_convert(resample_context,
- (uint8_t **)frame->extended_data, frame_sz,
- (const uint8_t **)&bfrp, frame_sz);
+ (uint8_t **)frame->extended_data, len,
+ (const uint8_t **)&bfrp, len);
if( ret < 0 ) {
ff_err(ret, "FFAudioStream::encode: swr_convert failed\n");
break;
}
+ frame->nb_samples = len;
frm->queue(curr_pos);
frm = 0;
- curr_pos += frame_sz;
- count -= frame_sz;
+ curr_pos += len;
+ count -= len;
}
delete frm;
return ret >= 0 ? 0 : 1;
}
+int FFAudioStream::drain()
+{
+ return encode(0,0);
+}
+
int FFAudioStream::encode_frame(AVFrame *frame)
{
return FFStream::encode_frame(frame);
int FFVideoStream::video_seek(int64_t pos)
{
- if( decode_activate() < 0 ) return -1;
+ if( decode_activate() <= 0 ) return -1;
if( !st->codecpar ) return -1;
if( pos == curr_pos-1 && !seeked ) return 0;
// if close enough, just read up to current
return ret >= 0 ? 0 : 1;
}
+int FFVideoStream::drain()
+{
+ return 0;
+}
+
int FFVideoStream::encode_frame(AVFrame *frame)
{
if( frame ) {
{
#if 1
double display_aspect = asset->width / (double)asset->height;
- double sample_aspect = asset->aspect_ratio / display_aspect;
+ double sample_aspect = display_aspect / asset->aspect_ratio;
int width = 1000000, height = width * sample_aspect + 0.5;
float w, h;
MWindow::create_aspect_ratio(w, h, width, height);
aud->sample_rate = avpar->sample_rate;
double secs = to_secs(st->duration, st->time_base);
aud->length = secs * aud->sample_rate;
- if( avpar->format != AV_SAMPLE_FMT_FLT ) {
- uint64_t layout = av_get_default_channel_layout(avpar->channels);
- if( !layout ) layout = ((uint64_t)1<<aud->channels) - 1;
- AVSampleFormat sample_format = (AVSampleFormat)avpar->format;
- aud->resample_context = swr_alloc_set_opts(NULL,
- layout, AV_SAMPLE_FMT_FLT, avpar->sample_rate,
- layout, sample_format, avpar->sample_rate,
- 0, NULL);
- swr_init(aud->resample_context);
- }
+ aud->init_swr(aud->channels, avpar->format, aud->sample_rate);
aud->nudge = st->start_time;
aud->reading = -1;
if( opt_audio_filter )
}
}
int64_t nudge = vstart_time > min_nudge ? vstart_time :
- astart_time > min_nudge ? astart_time : AV_NOPTS_VALUE;
+ astart_time > min_nudge ? astart_time : 0;
for( int vidx=0; vidx<ffvideo.size(); ++vidx ) {
if( ffvideo[vidx]->nudge == AV_NOPTS_VALUE )
ffvideo[vidx]->nudge = nudge;
mux_lock->lock("FFMPEG::run");
if( !done ) mux();
}
+ for( int i=0; i<ffaudio.size(); ++i )
+ ffaudio[i]->drain();
+ for( int i=0; i<ffvideo.size(); ++i )
+ ffvideo[i]->drain();
mux();
for( int i=0; i<ffaudio.size(); ++i )
ffaudio[i]->flush();
ret = avcodec_open2(avctx, decoder, &copts);
}
av_dict_free(&copts);
- if( ret < 0 ) {
- fprintf(stderr,"FFMPEG::scan: ");
- fprintf(stderr,_("codec open failed\n"));
- continue;
- }
- AVCodecParameters *avpar = st->codecpar;
- switch( avpar->codec_type ) {
- case AVMEDIA_TYPE_VIDEO: {
- int vidx = ffvideo.size();
- while( --vidx>=0 && ffvideo[vidx]->fidx != i );
- if( vidx < 0 ) break;
- ffvideo[vidx]->avctx = avctx;
- break; }
- case AVMEDIA_TYPE_AUDIO: {
- int aidx = ffaudio.size();
- while( --aidx>=0 && ffaudio[aidx]->fidx != i );
- if( aidx < 0 ) continue;
- ffaudio[aidx]->avctx = avctx;
- break; }
- default: break;
+ if( ret >= 0 ) {
+ AVCodecParameters *avpar = st->codecpar;
+ switch( avpar->codec_type ) {
+ case AVMEDIA_TYPE_VIDEO: {
+ int vidx = ffvideo.size();
+ while( --vidx>=0 && ffvideo[vidx]->fidx != i );
+ if( vidx < 0 ) break;
+ ffvideo[vidx]->avctx = avctx;
+ continue; }
+ case AVMEDIA_TYPE_AUDIO: {
+ int aidx = ffaudio.size();
+ while( --aidx>=0 && ffaudio[aidx]->fidx != i );
+ if( aidx < 0 ) break;
+ ffaudio[aidx]->avctx = avctx;
+ continue; }
+ default: break;
+ }
}
+ fprintf(stderr,"FFMPEG::scan: ");
+ fprintf(stderr,_("codec open failed\n"));
+ avcodec_free_context(&avctx);
}
decode_activate();
while( --vidx>=0 && ffvideo[vidx]->fidx != i );
if( vidx < 0 ) break;
FFVideoStream *vid = ffvideo[vidx];
+ if( !vid->avctx ) break;
int64_t tstmp = pkt.dts;
if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.pts;
if( tstmp != AV_NOPTS_VALUE && (pkt.flags & AV_PKT_FLAG_KEY) && pkt.pos > 0 ) {
while( --aidx>=0 && ffaudio[aidx]->fidx != i );
if( aidx < 0 ) break;
FFAudioStream *aud = ffaudio[aidx];
+ if( !aud->avctx ) break;
int64_t tstmp = pkt.pts;
if( tstmp == AV_NOPTS_VALUE ) tstmp = pkt.dts;
if( tstmp != AV_NOPTS_VALUE && (pkt.flags & AV_PKT_FLAG_KEY) && pkt.pos > 0 ) {
index_state->pad_data(ch, nch, aud->curr_pos);
}
while( (ret=aud->decode_frame(frame)) > 0 ) {
- if( frame->channels != nch ) break;
+ //if( frame->channels != nch ) break;
+ aud->init_swr(frame->channels, frame->format, frame->sample_rate);
float *samples;
int len = aud->get_samples(samples,
&frame->extended_data[0], frame->nb_samples);