2010-11-10 06:51:05 +01:00
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
#include <libavcodec/avcodec.h>
|
|
|
|
#include <libavformat/avformat.h>
|
|
|
|
#include <libavdevice/avdevice.h>
|
|
|
|
#include <libswscale/swscale.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
2012-02-13 23:34:36 +01:00
|
|
|
#include <ctype.h>
|
2012-03-02 11:31:15 +01:00
|
|
|
#include "../winlib/winlib.h"
|
2012-02-13 23:34:36 +01:00
|
|
|
|
2010-11-10 06:51:05 +01:00
|
|
|
#include "sound.h"
|
|
|
|
#include "fplay.h"
|
|
|
|
|
2012-03-02 11:31:15 +01:00
|
|
|
volatile enum player_state player_state;
|
2010-11-10 06:51:05 +01:00
|
|
|
|
|
|
|
uint32_t win_width, win_height;
|
|
|
|
|
|
|
|
void decoder();
|
|
|
|
|
|
|
|
AVFormatContext *pFormatCtx;
|
|
|
|
AVCodecContext *pCodecCtx;
|
|
|
|
AVCodecContext *aCodecCtx;
|
|
|
|
AVCodec *pCodec;
|
|
|
|
AVCodec *aCodec;
|
|
|
|
AVFrame *pFrame;
|
|
|
|
int videoStream;
|
|
|
|
int audioStream;
|
|
|
|
|
|
|
|
int have_sound = 0;
|
|
|
|
|
|
|
|
uint8_t *decoder_buffer;
|
|
|
|
extern int sample_rate;
|
2012-02-13 23:34:36 +01:00
|
|
|
char *movie_file;
|
|
|
|
|
|
|
|
|
|
|
|
queue_t q_video;
|
|
|
|
queue_t q_audio;
|
2010-11-10 06:51:05 +01:00
|
|
|
|
|
|
|
int main( int argc, char *argv[])
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if(argc < 2) {
|
|
|
|
printf("Please provide a movie file\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
movie_file = argv[1];
|
2010-11-10 06:51:05 +01:00
|
|
|
/* register all codecs, demux and protocols */
|
|
|
|
|
2012-02-28 09:45:00 +01:00
|
|
|
// av_log_set_level(AV_LOG_INFO);
|
|
|
|
|
2010-11-10 06:51:05 +01:00
|
|
|
avcodec_register_all();
|
|
|
|
avdevice_register_all();
|
|
|
|
av_register_all();
|
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
if( avformat_open_input(&pFormatCtx, argv[1], NULL, NULL) < 0)
|
2010-11-10 06:51:05 +01:00
|
|
|
{
|
|
|
|
printf("Cannot open file %s\n\r", argv[1]);
|
|
|
|
return -1; // Couldn't open file
|
|
|
|
};
|
|
|
|
|
2012-02-28 09:45:00 +01:00
|
|
|
// printf("%s\n\r", __FUNCTION__);
|
2010-11-10 06:51:05 +01:00
|
|
|
|
|
|
|
// Retrieve stream information
|
2012-02-13 23:34:36 +01:00
|
|
|
if(avformat_find_stream_info(pFormatCtx, NULL)<0)
|
2010-11-10 06:51:05 +01:00
|
|
|
{
|
|
|
|
printf("Cannot find streams\n\r");
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
// __asm__ __volatile__("int3");
|
2010-11-10 06:51:05 +01:00
|
|
|
|
2012-02-28 09:45:00 +01:00
|
|
|
// dump_format(pFormatCtx, 0, argv[1], 0);
|
2010-11-10 06:51:05 +01:00
|
|
|
|
|
|
|
// Find the first video stream
|
|
|
|
videoStream=-1;
|
|
|
|
audioStream=-1;
|
|
|
|
for(i=0; i < pFormatCtx->nb_streams; i++)
|
|
|
|
{
|
2012-02-13 23:34:36 +01:00
|
|
|
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO
|
2010-11-10 06:51:05 +01:00
|
|
|
&& videoStream < 0)
|
|
|
|
{
|
|
|
|
videoStream=i;
|
|
|
|
video_time_base = pFormatCtx->streams[i]->time_base;
|
|
|
|
|
|
|
|
}
|
2012-02-13 23:34:36 +01:00
|
|
|
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
|
2010-11-10 06:51:05 +01:00
|
|
|
audioStream < 0)
|
|
|
|
{
|
|
|
|
audioStream=i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(videoStream==-1)
|
|
|
|
{
|
|
|
|
printf("Video stream not detected\n\r");
|
|
|
|
return -1; // Didn't find a video stream
|
|
|
|
}
|
|
|
|
|
2012-03-02 11:31:15 +01:00
|
|
|
player_state = PLAY_RESTART;
|
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
// __asm__ __volatile__("int3");
|
2010-11-10 06:51:05 +01:00
|
|
|
|
|
|
|
// Get a pointer to the codec context for the video stream
|
|
|
|
pCodecCtx=pFormatCtx->streams[videoStream]->codec;
|
|
|
|
aCodecCtx=pFormatCtx->streams[audioStream]->codec;
|
|
|
|
|
|
|
|
// Find the decoder for the video stream
|
|
|
|
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
|
|
|
|
if(pCodec==NULL) {
|
2012-02-13 23:34:36 +01:00
|
|
|
printf("Unsupported codec with id %d for input stream %d\n",
|
|
|
|
pCodecCtx->codec_id, videoStream);
|
2010-11-10 06:51:05 +01:00
|
|
|
return -1; // Codec not found
|
|
|
|
}
|
2012-02-13 23:34:36 +01:00
|
|
|
|
|
|
|
if(avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
|
2010-11-10 06:51:05 +01:00
|
|
|
{
|
2012-02-13 23:34:36 +01:00
|
|
|
printf("Error while opening codec for input stream %d\n",
|
|
|
|
videoStream);
|
2010-11-10 06:51:05 +01:00
|
|
|
return -1; // Could not open codec
|
|
|
|
};
|
|
|
|
|
|
|
|
if (aCodecCtx->channels > 0)
|
|
|
|
aCodecCtx->request_channels = FFMIN(2, aCodecCtx->channels);
|
|
|
|
else
|
|
|
|
aCodecCtx->request_channels = 2;
|
|
|
|
|
|
|
|
aCodec = avcodec_find_decoder(aCodecCtx->codec_id);
|
|
|
|
|
|
|
|
if(aCodec)
|
|
|
|
{
|
2012-02-13 23:34:36 +01:00
|
|
|
if(avcodec_open2(aCodecCtx, aCodec, NULL) >= 0 )
|
2010-11-10 06:51:05 +01:00
|
|
|
{
|
|
|
|
WAVEHEADER whdr;
|
|
|
|
int fmt;
|
|
|
|
|
|
|
|
printf("audio stream rate %d channels %d\n",
|
|
|
|
aCodecCtx->sample_rate, aCodecCtx->channels);
|
|
|
|
|
|
|
|
whdr.riff_id = 0x46464952;
|
|
|
|
whdr.riff_format = 0x45564157;
|
|
|
|
whdr.wFormatTag = 0x01;
|
|
|
|
whdr.nSamplesPerSec = aCodecCtx->sample_rate;
|
|
|
|
whdr.nChannels = aCodecCtx->channels;
|
|
|
|
whdr.wBitsPerSample = 16;
|
|
|
|
|
|
|
|
sample_rate = aCodecCtx->sample_rate;
|
|
|
|
|
|
|
|
fmt = test_wav(&whdr);
|
|
|
|
|
|
|
|
if( init_audio(fmt) )
|
|
|
|
{
|
2012-02-13 23:34:36 +01:00
|
|
|
decoder_buffer = (uint8_t*)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE*2+64);
|
2010-11-10 06:51:05 +01:00
|
|
|
if( decoder_buffer != NULL )
|
|
|
|
{
|
|
|
|
astream.lock = 0;
|
|
|
|
astream.count = 0;
|
|
|
|
astream.buffer = (char *)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE*8);
|
|
|
|
if( astream.buffer != NULL )
|
|
|
|
have_sound = 1;
|
|
|
|
else
|
|
|
|
av_free(decoder_buffer);
|
|
|
|
}
|
|
|
|
if( have_sound == 0)
|
|
|
|
{
|
|
|
|
printf("Not enough memory for audio buffers\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else printf("Cannot open audio codec\n\r");
|
|
|
|
}
|
|
|
|
else printf("Unsupported audio codec!\n");
|
|
|
|
|
|
|
|
if( !init_video(pCodecCtx))
|
|
|
|
return 0;
|
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
// __asm__ __volatile__("int3");
|
2010-11-10 06:51:05 +01:00
|
|
|
|
|
|
|
decoder();
|
|
|
|
|
|
|
|
// Free the YUV frame
|
|
|
|
av_free(pFrame);
|
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
|
2010-11-10 06:51:05 +01:00
|
|
|
//__asm__ __volatile__("int3");
|
|
|
|
|
|
|
|
// Close the codec
|
|
|
|
// avcodec_close(pCodecCtx);
|
|
|
|
|
|
|
|
// Close the video file
|
|
|
|
// av_close_input_file(pFormatCtx);
|
|
|
|
|
|
|
|
//__asm__ __volatile__("int3");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void decoder()
|
|
|
|
{
|
2012-02-13 23:34:36 +01:00
|
|
|
int eof = 0;
|
|
|
|
AVPacket packet;
|
|
|
|
int ret;
|
2010-11-10 06:51:05 +01:00
|
|
|
|
2012-03-02 11:31:15 +01:00
|
|
|
while( player_state != CLOSED && !eof)
|
2010-11-10 06:51:05 +01:00
|
|
|
{
|
2012-02-13 23:34:36 +01:00
|
|
|
int err;
|
2010-11-10 06:51:05 +01:00
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
// __asm__ __volatile__("int3");
|
2010-11-10 06:51:05 +01:00
|
|
|
|
2012-03-02 11:31:15 +01:00
|
|
|
if( player_state == PAUSE )
|
|
|
|
{
|
|
|
|
delay(1);
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
|
2012-02-28 09:45:00 +01:00
|
|
|
if(q_video.size+q_audio.size < 12*1024*1024)
|
2012-02-13 23:34:36 +01:00
|
|
|
{
|
|
|
|
err = av_read_frame(pFormatCtx, &packet);
|
|
|
|
if( err < 0)
|
2010-11-10 06:51:05 +01:00
|
|
|
{
|
2012-02-13 23:34:36 +01:00
|
|
|
eof = 1;
|
|
|
|
if (err != AVERROR_EOF)
|
|
|
|
printf("av_read_frame: error %x\n", err);
|
|
|
|
continue;
|
2010-11-10 06:51:05 +01:00
|
|
|
}
|
2012-02-13 23:34:36 +01:00
|
|
|
if(packet.stream_index==videoStream)
|
|
|
|
{
|
|
|
|
put_packet(&q_video, &packet);
|
|
|
|
}
|
|
|
|
else if( (packet.stream_index == audioStream) &&
|
|
|
|
(have_sound != 0) )
|
|
|
|
{
|
|
|
|
put_packet(&q_audio, &packet);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
av_free_packet(&packet);
|
|
|
|
};
|
|
|
|
decode_video(pCodecCtx, &q_video);
|
|
|
|
decode_audio(aCodecCtx, &q_audio);
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
decode_video(pCodecCtx, &q_video);
|
|
|
|
decode_audio(aCodecCtx, &q_audio);
|
|
|
|
delay(1);
|
2010-11-10 06:51:05 +01:00
|
|
|
};
|
|
|
|
|
2012-02-13 23:34:36 +01:00
|
|
|
ret = 1;
|
2010-11-10 06:51:05 +01:00
|
|
|
|
2012-03-02 11:31:15 +01:00
|
|
|
while( (player_state != CLOSED) && ret)
|
2012-02-13 23:34:36 +01:00
|
|
|
{
|
|
|
|
ret = decode_video(pCodecCtx, &q_video);
|
|
|
|
ret |= decode_audio(aCodecCtx, &q_audio);
|
|
|
|
delay(1);
|
|
|
|
};
|
|
|
|
delay(50);
|
2012-03-02 11:31:15 +01:00
|
|
|
player_state = CLOSED;
|
2012-02-28 09:45:00 +01:00
|
|
|
delay(300);
|
2012-02-13 23:34:36 +01:00
|
|
|
};
|
2010-11-10 06:51:05 +01:00
|
|
|
|