15,7 → 15,9 |
#include "sound.h" |
#include "fplay.h" |
|
volatile enum player_state player_state; |
volatile enum player_state player_state = STOP; |
volatile enum player_state decoder_state = PREPARE; |
volatile enum player_state sound_state = STOP; |
|
uint32_t win_width, win_height; |
|
33,6 → 35,8 |
int have_sound = 0; |
|
uint8_t *decoder_buffer; |
extern int resampler_size; |
|
extern int sample_rate; |
char *movie_file; |
|
66,7 → 70,7 |
movie_file = argv[1]; |
/* register all codecs, demux and protocols */ |
|
// av_log_set_level(AV_LOG_INFO); |
av_log_set_level(AV_LOG_FATAL); |
|
avcodec_register_all(); |
avdevice_register_all(); |
133,8 → 137,6 |
return -1; // Didn't find a video stream |
} |
|
player_state = PLAY_INIT; |
|
// __asm__ __volatile__("int3"); |
|
// Get a pointer to the codec context for the video stream |
232,31 → 234,16 |
} |
|
|
static int fill_queue() |
static int load_frame() |
{ |
int eof = 0; |
AVPacket packet; |
|
while( !eof) |
{ |
int err; |
|
// __asm__ __volatile__("int3"); |
|
if(q_video.size+q_audio.size < 2*1024*1024) |
{ |
err = av_read_frame(pFormatCtx, &packet); |
if( err < 0) |
if( err == 0) |
{ |
eof = 1; |
if (err != AVERROR_EOF) |
printf("av_read_frame: error %x\n", err); |
break; |
} |
if(packet.stream_index==videoStream) |
{ |
put_packet(&q_video, &packet); |
} |
else if( (packet.stream_index == audioStream) && |
(have_sound != 0) ) |
{ |
263,124 → 250,163 |
put_packet(&q_audio, &packet); |
if(audio_base == -1.0) |
{ |
if (packet.dts != AV_NOPTS_VALUE) |
audio_base = get_audio_base() * packet.dts; |
if (packet.pts != AV_NOPTS_VALUE) |
audio_base = get_audio_base() * packet.pts; |
// printf("audio base %f\n", audio_base); |
}; |
} |
else |
{ |
av_free_packet(&packet); |
}; |
else av_free_packet(&packet); |
} |
else break; |
}; |
else if (err != AVERROR_EOF) |
printf("av_read_frame: error %x\n", err); |
|
return eof; |
return err; |
} |
|
}; |
|
|
void decoder() |
static int fill_queue() |
{ |
int eof; |
int err = 0; |
AVPacket packet; |
int ret; |
|
eof = fill_queue(); |
// __asm__ __volatile__("int3"); |
|
while( player_state != CLOSED && !eof) |
{ |
int err; |
while( (q_video.size+q_audio.size < 2*1024*1024) && |
!err ) |
err = load_frame(); |
|
// __asm__ __volatile__("int3"); |
return err; |
|
if( player_state == PAUSE ) |
{ |
delay(1); |
continue; |
}; |
|
if( player_state == REWIND ) |
|
static void flush_all() |
{ |
// int64_t timestamp = 0; |
// int stream_index = av_find_default_stream_index(pFormatCtx); |
AVPacket packet; |
|
// __asm__ __volatile__("int3"); |
|
if (pFormatCtx->start_time != AV_NOPTS_VALUE) |
rewind_pos += pFormatCtx->start_time; |
|
printf("rewind %8"PRId64"\n", rewind_pos); |
|
ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, |
rewind_pos, INT64_MAX, 0); |
// ret = avformat_seek_file(pFormatCtx, -1, 0, |
// 0, INT64_MAX, 0); |
// __asm__ __volatile__("int3"); |
|
if (ret < 0) |
{ |
printf("could not seek to position %f\n", |
(double)rewind_pos / AV_TIME_BASE); |
} |
else |
{ |
avcodec_flush_buffers(pCodecCtx); |
avcodec_flush_buffers(aCodecCtx); |
|
while( get_packet(&q_video, &packet) != 0) |
av_free_packet(&packet); |
|
while( get_packet(&q_audio, &packet)!= 0) |
av_free_packet(&packet); |
audio_base = -1.0; |
|
// __asm__ __volatile__("int3"); |
flush_video(); |
|
eof = fill_queue(); |
astream.count = 0; |
}; |
yield(); |
|
flush_video(); |
void decoder() |
{ |
int eof; |
AVPacket packet; |
int ret; |
int64_t min_pos, max_pos; |
|
player_state = REWIND_2_PLAY; |
printf("restart\n"); |
continue; |
}; |
while( player_state != CLOSED ) |
{ |
int err; |
|
if(q_video.size+q_audio.size < 4*1024*1024) |
// __asm__ __volatile__("int3"); |
|
switch(decoder_state) |
{ |
err = av_read_frame(pFormatCtx, &packet); |
if( err < 0) |
case PREPARE: |
eof = fill_queue(); |
|
do |
{ |
eof = 1; |
if (err != AVERROR_EOF) |
printf("av_read_frame: error %x\n", err); |
continue; |
} |
if(packet.stream_index==videoStream) |
if( (q_video.size+q_audio.size < 4*1024*1024) && |
(eof == 0) ) |
{ |
put_packet(&q_video, &packet); |
eof = load_frame(); |
} |
else if( (packet.stream_index == audioStream) && |
(have_sound != 0) ) |
decode_video(pCodecCtx, &q_video); |
ret = decode_audio(aCodecCtx, &q_audio); |
}while(astream.count < resampler_size*2 && |
ret == 1); |
|
sound_state = PREPARE; |
decoder_state = PLAY; |
player_state = PLAY; |
|
case PLAY: |
if( (q_video.size+q_audio.size < 4*1024*1024) && |
(eof == 0) ) |
{ |
put_packet(&q_audio, &packet); |
eof = load_frame(); |
if(eof) printf("eof\n"); |
} |
else |
ret = decode_video(pCodecCtx, &q_video); |
ret|= decode_audio(aCodecCtx, &q_audio); |
|
if( eof && !ret) |
{ |
av_free_packet(&packet); |
decoder_state = STOP; |
// printf("stop decoder\n"); |
}; |
decode_video(pCodecCtx, &q_video); |
decode_audio(aCodecCtx, &q_audio); |
continue; |
}; |
decode_video(pCodecCtx, &q_video); |
decode_audio(aCodecCtx, &q_audio); |
|
case STOP: |
delay(1); |
break; |
|
case PLAY_2_STOP: |
while(sound_state != STOP) |
delay(1); |
|
flush_all(); |
|
if (pFormatCtx->start_time != AV_NOPTS_VALUE) |
rewind_pos = pFormatCtx->start_time; |
else |
rewind_pos = 0; |
|
ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, |
rewind_pos, INT64_MAX, 0); |
|
decoder_state = STOP; |
break; |
|
case REWIND: |
while(sound_state != STOP) |
yield(); |
|
flush_all(); |
int opts = 0; |
if(rewind_pos < 0) |
{ |
rewind_pos = -rewind_pos; |
opts = AVSEEK_FLAG_BACKWARD; |
}; |
|
if (pFormatCtx->start_time != AV_NOPTS_VALUE) |
rewind_pos += pFormatCtx->start_time; |
|
// printf("rewind %8"PRId64"\n", rewind_pos); |
min_pos = rewind_pos - 1000000; |
max_pos = rewind_pos + 1000000; |
|
ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, |
rewind_pos, INT64_MAX, 0); |
|
// ret = avformat_seek_file(pFormatCtx, -1, min_pos, |
// rewind_pos, max_pos, opts); |
// __asm__ __volatile__("int3"); |
|
if (ret < 0) |
{ |
printf("could not seek to position %f\n", |
(double)rewind_pos / AV_TIME_BASE); |
} |
|
// printf("restart\n"); |
decoder_state = PREPARE; |
break; |
} |
}; |
|
ret = 1; |
|
while( (player_state != CLOSED) && ret) |