由于研究ffmpeg,有时候你需要音频原始数据PCM和视频原始数据YUV,所以自己写了一个类,用来产生原始数据。有的格式是可以的,但有的可是好像不行,原因为深入研究,现在也不弄音视频了,所以就放下了。半年前的东西那出来就是希望帮助到需要的人。
下面是头文件和cpp
decodec.h
#ifndef DECODEC_HH
#define DECODEC_HH
/************************************************
@描述:将输入的媒体文件解码成原始数据,(yuv and pcm);
**生成的音频数据可使用Audacity查看,->导入裸数据。。。
**生成的视频数据可使用ffplay查看,命令如:
ffplay -pix_fmt yuv420p -s 720x480 -i D:\FFM\No_mkv\yuv420p_720_480.yuv
@作者:毕竟小白
@日期:2015/3/3
*************************************************/
#ifdef __cplusplus
extern "C"
{
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#ifdef __cplusplus
};
#endif
#include <fstream>
#include <string>
#include <vector>
#include <map>
using namespace std;
class Decodec
{
public:
Decodec(string InFileName);
~Decodec(void);
void decodec();
private:
int openFile();
void closeFile();
void writeData();
void flushData();
private:
string m_InFile;
string m_dirFile;
ofstream m_vfout;
map<int, ofstream*> m_afout;
string m_outPath;
char* m_buff;
int m_buffSize;
AVFormatContext* m_ifmt_ctx;
};
#endif //DECODEC_HH
</pre><pre name="code" class="cpp">decodec.cpp
</pre><pre name="code" class="cpp">#include "Decodec.h"
#ifdef __cplusplus
extern "C"
{
#endif
#include "libavutil\pixdesc.h"
#ifdef __cplusplus
};
#endif
#include <iostream>
#include <direct.h>
Decodec::Decodec(std::string InFileName):m_InFile(InFileName)
{
m_buff = NULL;
m_buffSize = 0;
m_ifmt_ctx = NULL;
}
Decodec::~Decodec(void)
{
}
void Decodec::decodec()
{
if(m_InFile.empty())
{
cout << "InFile is empty!" << endl;
return;
}
av_register_all();
if(openFile() < 0) goto end;
writeData();
flushData();
end:
closeFile();
}
int Decodec::openFile()
{
int ret = 0;
ret = avformat_open_input(&m_ifmt_ctx, m_InFile.c_str(), NULL, NULL);
if (ret < 0)
{
cout << "Could not open input!" << endl;
return ret;
}
ret = avformat_find_stream_info(m_ifmt_ctx, NULL);
if (ret < 0)
{
cout << "Could not find stream information!" << endl;
return ret;
}
int pos = m_InFile.rfind('.');
m_dirFile = m_InFile.substr(0, pos);
if(pos < m_InFile.size())
m_dirFile = m_dirFile + "_" + m_InFile.substr(pos+1);
ret = _mkdir(m_dirFile.c_str());
// if(ret < 0)
// {
// cout << "Failed to creat directory !" << endl;
// return ret;
// }
for(int index = 0; index < m_ifmt_ctx->nb_streams; index++)
{
AVStream* stream = m_ifmt_ctx->streams[index];
AVCodecContext* codec_ctx = m_ifmt_ctx->streams[index]->codec;
AVCodec *codec = avcodec_find_decoder(codec_ctx->codec_id);
ret = avcodec_open2(codec_ctx, codec, NULL);
if(ret < 0)
{
cout << "Can't open this CodecContext, stream index is " << index << endl;
return ret;
}
char temp[64] = "";
if(AVMEDIA_TYPE_VIDEO == stream->codec->codec_type)
{
string pixfmt(av_get_pix_fmt_name(codec_ctx->pix_fmt));
string file = m_dirFile + "\\" + pixfmt + "_" + itoa(codec_ctx->width, temp, 10) +
"_" + itoa(codec_ctx->height, temp, 10) + ".yuv";
m_vfout.open(file.c_str(), ios::out|ios::binary);
if(!m_vfout.is_open()) return -1;
m_buffSize = avpicture_get_size(codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height);
m_buff = new char[m_buffSize];
if(NULL == m_buff) return -1;
}
else if(AVMEDIA_TYPE_AUDIO == stream->codec->codec_type)
{
string sample_fmt(av_get_sample_fmt_name(codec_ctx->sample_fmt));
string file = m_dirFile + "\\" + sample_fmt + "_" + itoa(codec_ctx->sample_rate, temp, 10) +
"_" + itoa(codec_ctx->channels, temp, 10) + "_" + itoa(index, temp, 10);
ofstream* fout = new ofstream;
fout->open(file.c_str(), ios::out|ios::binary);
if(!fout->is_open()) return -1;
m_afout[index] = fout;
}
}
return ret;
}
void Decodec::closeFile()
{
avformat_close_input(&m_ifmt_ctx);
if(m_buffSize != 0) delete[] m_buff;
if(m_vfout.is_open()) m_vfout.close();
for(map<int, ofstream*>::iterator iterMap = m_afout.begin();
iterMap != m_afout.end();
iterMap++)
{
iterMap->second->close();
delete iterMap->second;
}
}
void Decodec::writeData()
{
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
while (av_read_frame(m_ifmt_ctx, &pkt) >= 0)
{
AVFrame* frame = av_frame_alloc();
AVCodecContext* codec_ctx = m_ifmt_ctx->streams[pkt.stream_index]->codec;
int got_frame = 0, len = 0;
if(AVMEDIA_TYPE_AUDIO == codec_ctx->codec_type)
{
ofstream* fout = m_afout[pkt.stream_index];
len = avcodec_decode_audio4(codec_ctx, frame, &got_frame, &pkt);
if(len < 0)
{
cout << "Error while decoding !" << endl;
return;
}
if(got_frame)
{
int sampleByte = av_get_bytes_per_sample(codec_ctx->sample_fmt);
if(av_sample_fmt_is_planar(codec_ctx->sample_fmt))
{
for(int nbsample = 0; nbsample < frame->nb_samples; nbsample++)
{
for(int channel = 0; channel < frame->channels; ++channel)
{
fout->write(reinterpret_cast<char*>(frame->data[channel]+nbsample*sampleByte), sampleByte);
}
}
}
else
{
fout->write(reinterpret_cast<char*>(frame->data[0]), sampleByte*frame->nb_samples*frame->channels);
}
}
}
else if(AVMEDIA_TYPE_VIDEO == codec_ctx->codec_type)
{
len = avcodec_decode_video2(codec_ctx, frame, &got_frame, &pkt);
if(len < 0)
{
cout << "Error while decoding !" << endl;
return;
}
if(got_frame)
{
int ret = avpicture_layout(reinterpret_cast<const AVPicture*>(frame), codec_ctx->pix_fmt, frame->width, frame->height,
reinterpret_cast<unsigned char*>(m_buff), m_buffSize);
if(ret < 0) return;
m_vfout.write(m_buff, m_buffSize);
}
}
av_free_packet(&pkt);
av_frame_free(&frame);
}
}
void Decodec::flushData()
{
AVPacket pkt;
av_init_packet(&pkt);
pkt.data = NULL;
pkt.size = 0;
for(int index = 0; index < m_ifmt_ctx->nb_streams; ++index)
{
AVFrame* frame = av_frame_alloc();
AVCodecContext* codec_ctx = m_ifmt_ctx->streams[index]->codec;
int got_frame = 0, len = 0;
if(AVMEDIA_TYPE_AUDIO == codec_ctx->codec_type)
{
ofstream* fout = m_afout[index];
while( len = avcodec_decode_audio4(codec_ctx, frame, &got_frame, &pkt) )
{
if(len < 0) break;
if(got_frame)
{
int sampleByte = av_get_bytes_per_sample(codec_ctx->sample_fmt);
if(av_sample_fmt_is_planar(codec_ctx->sample_fmt))
{
for(int nbsample = 0; nbsample < frame->nb_samples; nbsample++)
{
for(int channel = 0; channel < frame->channels; ++channel)
{
fout->write(reinterpret_cast<char*>(frame->data[channel]+nbsample*sampleByte), sampleByte);
}
}
}
else
{
fout->write(reinterpret_cast<char*>(frame->data[0]), sampleByte*frame->nb_samples*frame->channels);
}
}
}
}
else if(AVMEDIA_TYPE_VIDEO == codec_ctx->codec_type)
{
while( len = avcodec_decode_video2(codec_ctx, frame, &got_frame, &pkt) )
{
if(len < 0) break;
if(got_frame)
{
<span style="white-space:pre"> </span>int ret = avpicture_layout(reinterpret_cast<const AVPicture*>(frame), codec_ctx->pix_fmt, frame->width,
frame->height, reinterpret_cast<unsigned char*>(m_buff), m_buffSize);
if(ret < 0) return;
m_vfout.write(m_buff, m_buffSize);
}
}
}
av_frame_free(&frame);
}
}
</pre><pre name="code" class="cpp"></pre><pre name="code" class="cpp">
main.cpp
</pre><pre name="code" class="cpp"></pre><pre name="code" class="cpp">#include "Decodec.h"
int main(void)
{
<span style="white-space:pre"> </span>Decodec de("test.mp4");
<span style="white-space:pre"> </span>de.decodec();
<span style="white-space:pre"> </span>return 0;
}
工程下载链接