音视频原始数据产生器

由于研究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;
}

工程下载链接

                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值