25,7 → 25,14 |
void decoder(); |
int fplay_init_context(AVCodecContext *avctx); |
|
AVFormatContext *pFormatCtx; |
AVCodecContext *pCodecCtx; |
AVCodecContext *aCodecCtx; |
AVCodec *pCodec; |
AVCodec *aCodec; |
AVFrame *pFrame; |
int videoStream; |
int audioStream; |
|
int have_sound = 0; |
|
37,7 → 44,8 |
|
void flush_video(); |
|
|
queue_t q_video; |
queue_t q_audio; |
int64_t rewind_pos; |
|
int64_t stream_duration; |
46,17 → 54,15 |
|
extern double audio_base; |
|
|
double get_audio_base(vst_t* vst) |
double get_audio_base() |
{ |
return (double)av_q2d(vst->fCtx->streams[vst->aStream]->time_base)*1000; |
return (double)av_q2d(pFormatCtx->streams[audioStream]->time_base)*1000; |
}; |
|
|
int main( int argc, char *argv[]) |
{ |
static vst_t vst; |
int i, ret; |
int i; |
char *file_name, *dot; |
|
if(argc < 2) |
78,16 → 84,16 |
avdevice_register_all(); |
av_register_all(); |
|
if( avformat_open_input(&vst.fCtx, movie_file, NULL, NULL) < 0) |
if( avformat_open_input(&pFormatCtx, movie_file, NULL, NULL) < 0) |
{ |
printf("Cannot open file %s\n\r", movie_file); |
return -1; // Couldn't open file |
}; |
|
vst.fCtx->flags |= AVFMT_FLAG_GENPTS; |
pFormatCtx->flags |= AVFMT_FLAG_GENPTS; |
|
// Retrieve stream information |
if(avformat_find_stream_info(vst.fCtx, NULL) < 0) |
if(avformat_find_stream_info(pFormatCtx, NULL)<0) |
{ |
printf("Cannot find streams\n\r"); |
return -1; |
103,33 → 109,32 |
} |
else movie_file = file_name; |
|
stream_duration = vst.fCtx->duration; |
stream_duration = pFormatCtx->duration; |
|
// Find the first video stream |
vst.vStream = -1; |
vst.aStream = -1; |
|
for(i=0; i < vst.fCtx->nb_streams; i++) |
videoStream=-1; |
audioStream=-1; |
for(i=0; i < pFormatCtx->nb_streams; i++) |
{ |
if(vst.fCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO |
&& vst.vStream < 0) |
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO |
&& videoStream < 0) |
{ |
vst.vStream = i; |
video_time_base = vst.fCtx->streams[i]->time_base; |
videoStream=i; |
video_time_base = pFormatCtx->streams[i]->time_base; |
if(stream_duration == 0) |
stream_duration = vst.fCtx->streams[i]->duration; |
stream_duration = pFormatCtx->streams[i]->duration; |
|
} |
|
if(vst.fCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && |
vst.aStream < 0) |
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && |
audioStream < 0) |
{ |
vst.aStream = i; |
audioStream=i; |
if(stream_duration == 0) |
stream_duration = vst.fCtx->streams[i]->duration; |
stream_duration = pFormatCtx->streams[i]->duration; |
} |
} |
|
if(vst.vStream==-1) |
if(videoStream==-1) |
{ |
printf("Video stream not detected\n\r"); |
return -1; // Didn't find a video stream |
138,45 → 143,44 |
// __asm__ __volatile__("int3"); |
|
// Get a pointer to the codec context for the video stream |
vst.vCtx = vst.fCtx->streams[vst.vStream]->codec; |
vst.aCtx = vst.fCtx->streams[vst.aStream]->codec; |
pCodecCtx = pFormatCtx->streams[videoStream]->codec; |
aCodecCtx = pFormatCtx->streams[audioStream]->codec; |
|
vst.vCodec = avcodec_find_decoder(vst.vCtx->codec_id); |
printf("codec id %x name %s\n",vst.vCtx->codec_id, vst.vCodec->name); |
printf("ctx->pix_fmt %d\n", vst.vCtx->pix_fmt); |
// Find the decoder for the video stream |
|
if(vst.vCodec == NULL) |
{ |
|
pCodec=avcodec_find_decoder(pCodecCtx->codec_id); |
|
// printf("ctx->pix_fmt %d\n", pCodecCtx->pix_fmt); |
|
if(pCodec==NULL) { |
printf("Unsupported codec with id %d for input stream %d\n", |
vst.vCtx->codec_id, vst.vStream); |
pCodecCtx->codec_id, videoStream); |
return -1; // Codec not found |
} |
|
|
|
|
if(avcodec_open2(vst.vCtx, vst.vCodec, NULL) < 0) |
if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0) |
{ |
printf("Error while opening codec for input stream %d\n", |
vst.vStream); |
videoStream); |
return -1; // Could not open codec |
}; |
|
// printf("ctx->pix_fmt %d\n", pCodecCtx->pix_fmt); |
|
mutex_init(&vst.q_video.lock); |
mutex_init(&vst.q_audio.lock); |
mutex_init(&vst.gpu_lock); |
mutex_init(&q_video.lock); |
mutex_init(&q_audio.lock); |
|
if (vst.aCtx->channels > 0) |
vst.aCtx->request_channels = FFMIN(2, vst.aCtx->channels); |
if (aCodecCtx->channels > 0) |
aCodecCtx->request_channels = FFMIN(2, aCodecCtx->channels); |
else |
vst.aCtx->request_channels = 2; |
aCodecCtx->request_channels = 2; |
|
vst.aCodec = avcodec_find_decoder(vst.aCtx->codec_id); |
aCodec = avcodec_find_decoder(aCodecCtx->codec_id); |
|
if(vst.aCodec) |
if(aCodec) |
{ |
if(avcodec_open2(vst.aCtx, vst.aCodec, NULL) >= 0 ) |
if(avcodec_open2(aCodecCtx, aCodec, NULL) >= 0 ) |
{ |
WAVEHEADER whdr; |
int fmt; |
183,15 → 187,15 |
int channels; |
|
printf("audio stream rate %d channels %d format %d\n", |
vst.aCtx->sample_rate, vst.aCtx->channels, vst.aCtx->sample_fmt ); |
aCodecCtx->sample_rate, aCodecCtx->channels, aCodecCtx->sample_fmt ); |
whdr.riff_id = 0x46464952; |
whdr.riff_format = 0x45564157; |
whdr.wFormatTag = 0x01; |
whdr.nSamplesPerSec = vst.aCtx->sample_rate; |
whdr.nSamplesPerSec = aCodecCtx->sample_rate; |
whdr.nChannels = 2; |
whdr.wBitsPerSample = 16; |
|
sample_rate = vst.aCtx->sample_rate; |
sample_rate = aCodecCtx->sample_rate; |
|
fmt = test_wav(&whdr); |
|
218,10 → 222,10 |
} |
else printf("Unsupported audio codec!\n"); |
|
if(!init_video(&vst)) |
if( !init_video(pCodecCtx)) |
return 0; |
|
decoder(&vst); |
decoder(); |
|
// Free the YUV frame |
av_free(pFrame); |
236,31 → 240,31 |
if(astream.lock.handle) |
mutex_destroy(&astream.lock); |
|
mutex_destroy(&vst.q_video.lock); |
mutex_destroy(&vst.q_audio.lock); |
mutex_destroy(&q_video.lock); |
mutex_destroy(&q_audio.lock); |
|
return 0; |
} |
|
|
static int load_frame(vst_t *vst) |
static int load_frame() |
{ |
AVPacket packet; |
int err; |
|
err = av_read_frame(vst->fCtx, &packet); |
err = av_read_frame(pFormatCtx, &packet); |
if( err == 0) |
{ |
if(packet.stream_index == vst->vStream) |
put_packet(&vst->q_video, &packet); |
else if( (packet.stream_index == vst->aStream) && |
if(packet.stream_index==videoStream) |
put_packet(&q_video, &packet); |
else if( (packet.stream_index == audioStream) && |
(have_sound != 0) ) |
{ |
put_packet(&vst->q_audio, &packet); |
put_packet(&q_audio, &packet); |
if(audio_base == -1.0) |
{ |
if (packet.pts != AV_NOPTS_VALUE) |
audio_base = get_audio_base(vst) * packet.pts; |
audio_base = get_audio_base() * packet.pts; |
// printf("audio base %f\n", audio_base); |
}; |
} |
274,28 → 278,30 |
|
|
|
static int fill_queue(vst_t* vst) |
static int fill_queue() |
{ |
int err = 0; |
AVPacket packet; |
|
while( (vst->q_video.size < 4*1024*1024) && !err ) |
err = load_frame(vst); |
while( (q_video.size < 4*1024*1024) && |
!err ) |
err = load_frame(); |
|
return err; |
|
}; |
|
|
static void flush_all(vst_t* vst) |
static void flush_all() |
{ |
AVPacket packet; |
|
avcodec_flush_buffers(vst->vCtx); |
avcodec_flush_buffers(vst->aCtx); |
while( get_packet(&vst->q_video, &packet) != 0) |
avcodec_flush_buffers(pCodecCtx); |
avcodec_flush_buffers(aCodecCtx); |
while( get_packet(&q_video, &packet) != 0) |
av_free_packet(&packet); |
|
while( get_packet(&vst->q_audio, &packet)!= 0) |
while( get_packet(&q_audio, &packet)!= 0) |
av_free_packet(&packet); |
|
flush_video(); |
303,7 → 309,7 |
astream.count = 0; |
}; |
|
void decoder(vst_t* vst) |
void decoder() |
{ |
int eof; |
AVPacket packet; |
320,17 → 326,17 |
switch(decoder_state) |
{ |
case PREPARE: |
eof = fill_queue(vst); |
eof = fill_queue(); |
|
do |
{ |
if( (vst->q_video.size < 4*1024*1024) && |
if( (q_video.size < 4*1024*1024) && |
(eof == 0) ) |
{ |
eof = load_frame(vst); |
eof = load_frame(); |
} |
decode_video(vst); |
ret = decode_audio(vst->aCtx, &vst->q_audio); |
decode_video(pCodecCtx, &q_video); |
ret = decode_audio(aCodecCtx, &q_audio); |
}while(astream.count < resampler_size*2 && |
ret == 1); |
|
339,13 → 345,13 |
player_state = PLAY; |
|
case PLAY: |
if( (vst->q_video.size < 4*1024*1024) && |
if( (q_video.size < 4*1024*1024) && |
(eof == 0) ) |
{ |
eof = load_frame(vst); |
eof = load_frame(); |
} |
vret = decode_video(vst); |
aret = decode_audio(vst->aCtx, &vst->q_audio); |
vret = decode_video(pCodecCtx, &q_video); |
aret = decode_audio(aCodecCtx, &q_audio); |
ret = vret | aret; |
|
if( eof && !ret) |
356,10 → 362,10 |
|
if( (vret & aret) == -1) |
{ |
if( (vst->q_video.size < 4*1024*1024) && |
if( (q_video.size < 4*1024*1024) && |
(eof == 0) ) |
{ |
eof = load_frame(vst); |
eof = load_frame(); |
yield(); |
continue; |
}; |
379,14 → 385,14 |
while(sound_state != STOP) |
delay(1); |
|
flush_all(vst); |
flush_all(); |
|
if (vst->fCtx->start_time != AV_NOPTS_VALUE) |
rewind_pos = vst->fCtx->start_time; |
if (pFormatCtx->start_time != AV_NOPTS_VALUE) |
rewind_pos = pFormatCtx->start_time; |
else |
rewind_pos = 0; |
|
ret = avformat_seek_file(vst->fCtx, -1, INT64_MIN, |
ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, |
rewind_pos, INT64_MAX, 0); |
|
decoder_state = STOP; |
396,7 → 402,7 |
while(sound_state != STOP) |
yield(); |
|
flush_all(vst); |
flush_all(); |
int opts = 0; |
if(rewind_pos < 0) |
{ |
404,23 → 410,27 |
opts = AVSEEK_FLAG_BACKWARD; |
}; |
|
if (vst->fCtx->start_time != AV_NOPTS_VALUE) |
rewind_pos += vst->fCtx->start_time; |
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(vst->fCtx, -1, INT64_MIN, |
ret = avformat_seek_file(pFormatCtx, -1, INT64_MIN, |
rewind_pos, INT64_MAX, 0); |
|
if (ret < 0) |
{ |
printf("could not seek to position %f\n", |
(double)rewind_pos / AV_TIME_BASE); |
} |
|
// printf("restart\n"); |
decoder_state = PREPARE; |
break; |
} |
}; |
|
}; |
|