65,186
社区成员




// input file info
AVFormatContext* ic;
AVStream* ist;
// output file info
AVFormatContext* oc;
AVStream* ost;
int m_nBufferSize;
BYTE* m_byBuffer;
// 初始化
nt CConvertManager::Init()
{
avcodec_register_all();
avdevice_register_all();
avfilter_register_all();
av_register_all();
return 0;
}
// 处理输入文件
int CConvertManager::AnalyzeInputFile(const char* fileName)
{
AVInputFormat* iFormat = NULL;
AVFormatParameters params, *ap = ¶ms;
AVCodecContext* icc = NULL;
AVCodec* codec = NULL;
int ret;
ic = avformat_alloc_context();
if (!ic)
{
return -1;
}
memset(ap, 0, sizeof(AVFormatParameters));
ap->prealloced_context = 1;
// open input file with generic libav function
ret = av_open_input_file(&ic, fileName, NULL, 0, NULL);
if (ret < 0)
{
return -1;
}
// decode the first frames to get the stream parameters
ret = av_find_stream_info(ic);
if (ret < 0)
{
av_close_input_file(ic);
return -1;
}
videoIndex = -1;
for (int i = 0; i < ic->nb_streams; i++)
{
if (ic->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoIndex = i;
}
}
if (videoIndex == -1)
{
return -1;
}
ist = ic->streams[videoIndex];
icc = ist->codec;
// find the video encoder
codec = avcodec_find_decoder(icc->codec_id);
// open codec
if (avcodec_open(icc, codec) < 0)
{
return -1;
}
return 0;
}
// 处理输部门文件
int CConvertManager::AnalyzeOutputFile(const char* fileName)
{
AVOutputFormat* oFormat = NULL;
AVFormatParameters params, *ap = ¶ms;
AVCodecContext* occ = NULL;
enum CodecID codec_id = CODEC_ID_NONE;
AVCodec* codec = NULL;
int ret;
oFormat = av_guess_format(NULL, fileName, NULL);
if (!oFormat)
{
return -1;
}
oc = avformat_alloc_context();
if (!oc)
{
return -1;
}
oc->oformat = oFormat;
strcpy_s(oc->filename, fileName);
// create video stream
ost = av_new_stream(oc, 0);
// guess codec
codec_id = av_guess_codec(oFormat, NULL, oc->filename, NULL, AVMEDIA_TYPE_VIDEO);
codec = avcodec_find_encoder(codec_id);
occ = avcodec_alloc_context();
av_dict_copy(&ost->metadata, ist->metadata, AV_DICT_DONT_OVERWRITE);
av_dict_copy(&oc->metadata, ic->metadata, AV_DICT_DONT_OVERWRITE);
occ = ost->codec;
occ->codec_id = codec_id;
occ->codec_type = AVMEDIA_TYPE_VIDEO;
occ->width = ist->codec->width;
occ->height = ist->codec->height;
AVRational rational;
if (ist->r_frame_rate.num)
{
rational.den = ist->r_frame_rate.num;
rational.num = ist->r_frame_rate.den;
}
else
{
rational.den = 1;
rational.num = 25;
}
occ->time_base = rational;
occ->gop_size = ist->codec->gop_size;
occ->pix_fmt = ist->codec->pix_fmt;
occ->max_b_frames = ist->codec->max_b_frames;
occ->bits_per_raw_sample = ist->codec->bits_per_raw_sample;
occ->chroma_sample_location = ist->codec->chroma_sample_location;
ost->r_frame_rate = ist->r_frame_rate;
ost->disposition = ist->disposition;
// open the file
ret = avio_open(&oc->pb, fileName, AVIO_FLAG_WRITE);
if (ret < 0)
{
return -1;
}
memset(ap, 0, sizeof(AVFormatParameters));
if (av_set_parameters(oc, NULL) < 0)
{
return -1;
}
if (avcodec_open(occ, codec)<0)
{
return -1;
}
return 0;
}
// 格式转换
int CConvertManager::Convert(const char* srcFile, const char* destFile, float rate)
{
AnalyzeInputFile(srcFile);
AnalyzeOutputFile(destFile);
AVFrame *picture = NULL;
int ret = 0;
if (ost->codec->codec_type == AVMEDIA_TYPE_VIDEO)
{
int size = ost->codec->width * ost->codec->height;
m_nBufferSize = FFMAX(BUFFER_SIZE, 7*size + 10000);
}
if (!m_byBuffer)
{
m_byBuffer = (BYTE*)av_malloc(m_nBufferSize);
}
if (!m_byBuffer)
{
return -1;
}
picture = avcodec_alloc_frame();
// open files and write file headers
if (av_write_header(oc) < 0)
{
return -1;
}
int frameIndex = 0;
while (ret >= 0)
{
memset(m_byBuffer, 0, m_nBufferSize);
AVPacket packet;
ret = av_read_frame(ic, &packet);
if (ret == AVERROR(EAGAIN))
{
break;
}
if (ret < 0)
{
break;
}
// is the video stream
if (packet.stream_index == videoIndex)
{
int got_output = 0;
ret = avcodec_decode_video2(ist->codec, picture, &got_output, &packet);
if (got_output)
{
picture->pts = av_rescale(frameIndex, AV_TIME_BASE*(int64_t)ost->codec->time_base.num, ost->codec->time_base.den);
picture->pict_type = AV_PICTURE_TYPE_NONE;
int outSize = avcodec_encode_video(ost->codec, m_byBuffer, m_nBufferSize, picture);
if (outSize > 0)
{
AVPacket pkt;
av_init_packet(&pkt);
if (ost->codec->coded_frame && ost->codec->coded_frame->key_frame)
{
pkt.flags |= AV_PKT_FLAG_KEY;
}
pkt.stream_index = ost->index;
pkt.data = m_byBuffer;
pkt.size = outSize;
ret = av_write_frame(oc, &pkt);
}
}
else
{
av_write_frame(oc, &packet);
}
}
frameIndex++;
}
// write the trailer
av_write_trailer(oc);
return 0;
}