本文主要是介绍FFmpeg编解码的那些事(2),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
软解码
1.构建输入AVFormatContext
AVFormatContext* avFormatContext = avformat_alloc_context();int res = avformat_open_input(&avFormatContext,filename.toUtf8().data(), NULL, NULL);//打开文件if (res < 0) {qCritical()<<__FUNCTION__<<__LINE__<<"error "<<res<<"in avformat_open_input";return res;}
2.查找视频信息流
res = avformat_find_stream_info(avFormatContext, nullptr);//取出流信息if (res < 0){return res;}//查找视频流和音频流av_dump_format(avFormatContext, 0,filename.toUtf8().data(), 0);//列出输入文件的相关流信息for (unsigned int i = 0; i < avFormatContext->nb_streams; i++){if (avFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){if(video_index==-1){video_index = i;}}}m_width = avFormatContext->streams[video_index]->codec->width;m_height = avFormatContext->streams[video_index]->codec->height;
3.初始化软解码
AVCodecContext *avCodecContext = avFormatContext->streams[video_index]->codec;AVCodec* m_codec = avcodec_find_decoder(avCodecContext->codec_id);if (avcodec_open2(avCodecContext, m_codec, NULL) < 0){return false;}
4.初始化SwsContext图像转换上下文
img_convert_ctx = sws_getContext(m_width,m_height,avCodecContext->pix_fmt,m_width,m_height,AV_PIX_FMT_BGRA,SWS_BICUBIC,NULL, NULL, NULL);
5.循环读取数据
while (true){int ret = av_read_frame(avFormatContext, avPacket);if (ret < 0){qDebug()<< "read end";break;}else if (avPacket->stream_index == video_index){decode_to_photo(avPacket);}av_packet_unref(avPacket);}void decode_to_photo(const AVPacket *avPacket)
{int ret = avcodec_send_packet(avCodecContext, avPacket);if (ret < 0) {char error[1024];av_strerror(ret, error, 1024);qDebug() << "发送解码失败:" << error;}while (true){ret = avcodec_receive_frame(avCodecContext, avFrame);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){//qDebug() << "avcodec_receive_frame end:" << ret;break;}else if (ret < 0){//qDebug()<< "获取解码数据失败"<<ret;return;}else{QImage pixLogo2;int m_rotat = getRotateAngle(avFormatContext->streams[video_index]);if(dec_st == AV_SOFTWARE_DECODER){sws_scale(img_convert_ctx,(const unsigned char* const*)avFrame->data,avFrame->linesize, 0,avFrame->height,bgrFrame->data,bgrFrame->linesize);QImage pixLogo(bgrFrame->data[0],bgrFrame->width,bgrFrame->height,bgrFrame->width * 4, QImage::Format_ARGB32);QMatrix matrix;matrix.rotate(m_rotat);pixLogo2 = pixLogo.transformed(matrix,Qt::FastTransformation);/*这里可以进行必要的图片处理操作*/}curcount++;av_frame_unref(sw_frame);av_frame_unref(avFrame);}}
}
tips:
根据pts来计算一桢在整个视频中的时间位置
timestamp(秒) = pts * av_q2d(st->time_base)
timestamp(毫秒) = pts * av_q2d(st->time_base) * 1000
计算视频长度的方法
time(秒) = st->duration * av_q2d(st->time_base)
这篇关于FFmpeg编解码的那些事(2)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!