[FFmpeg-user] playing a stream at the correct speed from a file. help needed please
JULIAN GARDNER
joolzg at btinternet.com
Thu Apr 2 14:18:01 CEST 2015
I have a thread that I am trying and failing to get to play a stream from disc as the correct rate.
I have an input thread which does this in its packet loop, code is in to pause and resume the process depending on how many frames have been buffered.
while (!inputSource->quit && !stop_all_tasks && av_read_frame(inputSource->fmt_ctx, &inputSource->pkt) >= 0) {
int cnt;
do {
ret = decode_packet(&got_frame, 0, inputSource);
if (ret < 0)
break;
inputSource->pkt.data += ret;
inputSource->pkt.size -= ret;
} while (!inputSource->quit && !stop_all_tasks && inputSource->pkt.size > 0);
cnt = localNumberOfPackets( inputSource, VIDEO_INDEX);
if( cnt>25) {
do {
sleep(1);
cnt = localNumberOfPackets( inputSource, VIDEO_INDEX);
} while( !inputSource->quit && !stop_all_tasks && cnt>15);
}
}
}
now the decode_packet does this, all standard stuff
if (inputSource->pkt.stream_index == inputSource->video_stream_idx) {
/* decode video frame */
ret = avcodec_decode_video2(inputSource->video_dec_ctx, frame, got_frame, &inputSource->pkt);
if (ret < 0) {
fprintf(stderr, "Error decoding video frame (%s)\n", av_err2str(ret));
return ret;
}
index = VIDEO_INDEX;
} else if (inputSource->pkt.stream_index == inputSource->audio_stream_idx) {
/* decode audio frame */
ret = avcodec_decode_audio4(inputSource->audio_dec_ctx, frame, got_frame, &inputSource->pkt);
if (ret < 0) {
fprintf(stderr, "Error decoding audio frame (%s)\n", av_err2str(ret));
return ret;
}
/* Some audio decoders decode only part of the packet, and have to be
* called again with the remainder of the packet data.
* Sample: fate-suite/lossless-audio/luckynight-partial.shn
* Also, some decoders might over-read the packet. */
decoded = FFMIN(ret, inputSource->pkt.size);
index = AUDIO_INDEX;
}
if( *got_frame && index<MAX_INDEX) {
videoFrames *current = calloc( 1, sizeof( videoFrames));
double pts;
if( (pts = av_frame_get_best_effort_timestamp( frame))==AV_NOPTS_VALUE) {
pts = 0;
}
if( index==VIDEO_INDEX)
pts *= av_q2d(inputSource->video_dec_ctx->time_base);
else
pts *= av_q2d(inputSource->audio_dec_ctx->time_base);
current->frame = frame;
current->pts = pts;
current->next = NULL;
localAddPacketToList( inputSource, index, current);
}
And finally where i seem to be having the problem the, video decode thread
double frame_delay;
double basicDelay = av_q2d(inputSource->video_dec_ctx->time_base) * inputSource->video_dec_ctx->ticks_per_frame;
NextPts = PrePts = 0;
gettimeofday(&start_time, NULL);
start_usec = TIMEOFDAY(start_time);
while( !inputSource->quit && !stop_all_tasks) {
int cnt = localNumberOfPackets( inputSource, VIDEO_INDEX);
if( cnt) {
videoFrames *here;
AVFrame *frame;
int t;
double pts;
pthread_mutex_lock( &inputSource->list_mutex);
here = inputSource->packets_list[VIDEO_INDEX];
inputSource->packets_list[VIDEO_INDEX] = here->next;
frame = here->frame;
pts = here->pts;
pthread_mutex_unlock( &inputSource->list_mutex);
// code from github, 3rd try See values at end
if( !NextPts && !PrePts) {
NextPts = PrePts = frame->pkt_pts;
}
if( frame->pkt_pts != AV_NOPTS_VALUE) {
drift = frame->pkt_pts - NextPts;
NextPts = ( frame->pkt_pts - PrePts) + frame->pkt_pts;
Delay = NextPts - frame->pkt_pts - drift;
if( Delay < 0)
Delay = 0;
frame_delay = Delay * 1000 * av_q2d( inputSource->video_dec_ctx->time_base);
PrePts = frame->pkt_pts;
}
else {
frame_delay = basicDelay * frame->repeat_pict * (basicDelay * 0.5);
frame_delay *= 1000;
}
frame_delay = FFMIN( frame_delay, 200);
if( inputSource->video_dec_ctx->codec_id == AV_CODEC_ID_H264) {
frame_delay = FFMAX( frame_delay, 10);
}
printf( "Frame Display delay:%f drift:%8ld next:%8ld prev:%8ld Delay:%8ld (%d)\r\n", frame_delay, drift, NextPts, PrePts, Delay, cnt);
usleep( frame_delay * 1000);
if (frame->key_frame) {
if (verbose) {
printf("%s video_frame n:%d coded_n:%d pts:%s %f %c\n",
inputSource->name, inputSource->video_frame_count, frame->display_picture_number,
av_ts2timestr(frame->pts, &inputSource->video_dec_ctx->time_base), here->pts,
frame->key_frame ? 'K':' ');
}
}
}
Now the problem is the stream does not play at the corerct speed and i have cannot see why this fails. I have tried 3 different ways and the one above is taken from a videoplayer on github.
Examples of files/streams tried
Live stream - time_base:1/50 ticks_per_frame:2 delay:8 framerate:25/1 pkt_timebase:1/90000
Stream #0:0[0x100]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p, 720x288 [SAR 32:45 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
Frame Display delay:10.000000 drift: 0 next:8317753200 prev:8317753200 Delay: 0 (9,0)
Frame Display delay:10.000000 drift: 3600 next:8317760400 prev:8317756800 Delay: 0 (9,0)
Frame Display delay:200.000000 drift: 0 next:8317764000 prev:8317760400 Delay: 3600 (9,5)
Mp4 File - time_base:1/50 ticks_per_frame:2 delay:8 framerate:25/1 pkt_timebase:1/100
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 720x544 [SAR 1:1 DAR 45:34], 1391 kb/s, 25 fps, 25 tbr, 100 tbn, 50 tbc (default)
Frame Display delay:10.000000 drift: 0 next: 8 prev: 8 Delay: 0 (10,15)
Frame Display delay:10.000000 drift: 4 next: 16 prev: 12 Delay: 0 (20,30)
Frame Display delay:80.000000 drift: 0 next: 20 prev: 16 Delay: 4 (31,44)
Mp4 File - time_base:1/60000 ticks_per_frame:2 delay:8 framerate:0/1 pkt_timebase:1/30000
Stream #0:1(und): Video: h264 (Baseline) (avc1 / 0x31637661), yuv420p, 480x320 [SAR 1:1 DAR 3:2], 501 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 60k tbc (default)
Frame Display delay:10.000000 drift: 0 next: 0 prev: 0 Delay: 0 (15,43)
Frame Display delay:10.000000 drift: 0 next: 1001 prev: 1001 Delay: 0 (66,109)
Frame Display delay:10.000000 drift: 1001 next: 3003 prev: 2002 Delay: 0 (103,175)
Frame Display delay:16.683333 drift: 0 next: 4004 prev: 3003 Delay: 1001 (142,230)
Frame Display delay:16.683333 drift: 0 next: 5005 prev: 4004 Delay: 1001 (214,328)
Can anyone help or point me in the direction of code that will show me the errors in my ways? I would like to be able to work out the delays needed for any file type.
joolz
More information about the ffmpeg-user
mailing list