extern "C" {
#include "libavcodec\avcodec.h"
#include "libavformat\avformat.h"
#include "libavutil\avutil.h"
}
class FileReader
{
public:
public:
FileReader();
virtual ~FileReader();
int openFile(char *filename);
void closeFile();
int running();
...
int seek(int pos);
protected:
AVFormatContext *m_pFormatContext;
AVPacket m_avPacket;
AVIndexEntry *m_pIndexEntries;
int m_nIndexEntries;
enum CodecID m_nVideoCodecId;
int m_nWidth, m_nHeight;
int m_nVideoStreamId, m_nAudioStreamId;
...
BOOL m_bReadThreadRun;
};
< FileReader.cpp >
#include "FileReader.h"
FileReader::FileReader()
{
static int init = 0;
if (init == 0)
{
WaitForSingleObject(hMutexCodec, INFINITE);
WaitForSingleObject(hMutexCodec, INFINITE);
av_register_all();
ReleaseMutex(hMutexCodec);
init = 1;
}
m_pFormatContext = NULL;
m_nVideoStreamId = m_nAudioStreamId = AVMEDIA_TYPE_UNKNOWN;
m_pIndexEntries = NULL;
m_nIndexEntries = 0;
m_bReadThreadRun = false;
}
FileReader::~FileReader()
{
closeFile();
}
int FileReader::openFile(char *filepath)
{
int err;
#ifdef FFMPEG_0_8
err = av_open_input_file(&m_pFormatContext, filepath, NULL, 0, NULL);
#else
err = avformat_open_input(&m_pFormatContext, filepath, NULL, NULL);
#endif
#else
err = avformat_open_input(&m_pFormatContext, filepath, NULL, NULL);
#endif
if (err < 0) {
printf("[%d] av_open_input_file: error %d\n", __FUNCTION__, err);
return -2;
}
err = av_find_stream_info(m_pFormatContext);
if (err < 0) {
printf("[%d] av_find_stream_info: error %d\n", __FUNCTION__, err);
closeFile();
return -2;
}
av_init_packet(&m_avPacket);
AVCodecContext *videoCodec = NULL;
for (int i=0; i<m_pFormatContext->nb_streams; i++)
{
{
AVStream *stream = m_pFormatContext->streams[i];
if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoCodec = stream->codec;
m_nWidth = videoCodec->width;
m_nHeight = videoCodec->height;
m_pIndexEntries = stream->index_entries;
m_nIndexEntries = stream->nb_index_entries;
m_nVideoCodecId = videoCodec->codec_id;
m_nVideoStreamId = stream->id;
}
else if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
{
m_nAudioStreamId = stream->id;
...
}
}
return 0;
}
void FileReader::closeFile()
{
if (m_pFormatContext) {
av_free_packet(&m_avPacket);
av_close_input_file(m_pFormatContext);
m_pFormatContext = NULL;
m_pIndexEntries = NULL;
m_nIndexEntries = 0;
}
}
int FileReader::running()
{
int err;
while (m_bReadThreadRun)
{
err = av_read_frame(m_pFormatContext, &m_avPacket);
if (err < 0)
{
Sleep(10);
continue;
}
if (m_avPacket.stream_index == m_nVideoStreamId)
{
process video stream here...
}
else if (m_avPacket.stream_index == m_nAudioStreamId)
{
process audio stream here...
}
av_free_packet(&m_avPacket);
Sleep(10);
}
return 0;
}
int FileReader::seek(int pos)
{
if (m_pFormatContext)
//return av_seek_frame(m_pFormatContext, m_nVideoStreamId, pos, AVSEEK_FLAG_BYTE); // file position 으로 seek
return av_seek_frame(m_pFormatContext, m_nVideoStreamId, pos, AVSEEK_FLAG_FRAME); // frame count 로 seek
//return av_seek_frame(m_pFormatContext, m_nVideoStreamId, pos, AVSEEK_FLAG_BYTE); // file position 으로 seek
return av_seek_frame(m_pFormatContext, m_nVideoStreamId, pos, AVSEEK_FLAG_FRAME); // frame count 로 seek
return -1;
}
댓글 없음:
댓글 쓰기