代码拉取完成,页面将自动刷新
#include "decodevideothread.h"
DecodeVideoThread::DecodeVideoThread(QObject *parent,int w,int h,void(*callBack)(uint8_t ** data,int * linesize))
{
_videoW=w;
_videoH=h;
_frameCallback=callBack;
}
int DecodeVideoThread::checkVideoInfo(AVFormatContext *avFormatCtx){
//SDLRender(NULL);
_avFormatCtx=avFormatCtx;
_videoIndex=-1;
//01 获取视频流序号
int _videoIndex=av_find_best_stream(avFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
if(_videoIndex<0)
return -1;
//02 获取视频编解码信息
_avCodecParameters=avFormatCtx->streams[_videoIndex]->codecpar;
//03 获取解码器
// int err = 0;
// AVBufferRef *hw_device_ctx = NULL;
// if ((err = av_hwdevice_ctx_create(&hw_device_ctx, AVHWDeviceType::AV_HWDEVICE_TYPE_OPENCL,
// NULL, NULL, 0)) < 0) {
// fprintf(stderr, "Failed to create specified HW device.\n");
// return err;
// }
// _videoCodecCtx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
AVCodec *videoCodec = avcodec_find_decoder_by_name("h264");
//AVCodec *videoCodec= avcodec_find_decoder(_videoCodecCtx->codec_id);
//AVCodec *videoCodec = avcodec_find_decoder_by_name("h264_cuvid");
if (!videoCodec) {
printf("不支持硬解码");
videoCodec= avcodec_find_decoder(_avCodecParameters->codec_id);
}else{
//todo:调用硬解码需要设置pix_fmt格式,软件不需要
if(nullptr!=videoCodec->pix_fmts){
_avCodecParameters->format=videoCodec->pix_fmts[0];
}else{
//_videoCodecCtx->pix_fmt=AV_PIX_FMT_NV12;
}
}
//04 初始化视频解码器结构
_videoCodecCtx= avcodec_alloc_context3(videoCodec);
if(_videoCodecCtx==NULL){
printf("could not allocate AVCodecContext.\n");
return -1;
}
avcodec_parameters_to_context(_videoCodecCtx,_avCodecParameters);
if(avcodec_open2(_videoCodecCtx,videoCodec,NULL)<0)
{
//初始化解码器失败
return -1;
}
//05 创建视频帧
_videoFrame=av_frame_alloc();
//06 创建动态内存,存储图像空间
int width=_avCodecParameters->width;
int height=_avCodecParameters->height;
if(width==0)
return -1;
if(height==0)
return -1;
_outVideoBuffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P,_videoW,_videoH,1));
av_image_fill_arrays(_videoFrame->data,_videoFrame->linesize,_outVideoBuffer,AV_PIX_FMT_YUV420P,_videoW,_videoH,1);
//AVPacket *_packet=(AVPacket*)av_malloc(sizeof (AVPacket));
//07 初始化图像转换结构
_videoSwsCxt= sws_getContext(width,height,static_cast<AVPixelFormat>(_avCodecParameters->format),_videoW,_videoH,AV_PIX_FMT_YUV420P,SWS_BICUBIC,
NULL, NULL, NULL);
_run=true;
return _videoIndex;
}
void DecodeVideoThread::changeSize(int w, int h){
_videoW=w;
_videoH=h;
}
void DecodeVideoThread::addFrame(AVPacket *packet ){
_frameQueueLock.lock();
if(_frameQueue.size()>5)
{
while (_frameQueue.size()>0) {
AVPacket *pkt = _frameQueue.front();
_frameQueue.pop();
av_packet_unref(pkt);
}
}
AVPacket *copyPacket= av_packet_clone(packet);
_frameQueue.push(copyPacket);
_frameQueueLock.unlock();
}
void DecodeVideoThread::run(){
while (_run) {
_frameQueueLock.lock();
if(!_frameQueue.empty()){
//AVPacket *packet=_frameQueue.dequeue();
AVPacket *packet=_frameQueue.front();
_frameQueue.pop();
_frameQueueLock.unlock();
decode(packet);
av_packet_unref(packet);
}else{
_frameQueueLock.unlock();
QThread::msleep(10);
}
}
sws_freeContext(_videoSwsCxt);
avcodec_free_context(&_videoCodecCtx);
}
void DecodeVideoThread::decode(AVPacket *packet){
if(!_run)
return;
//int got_picture_ptr;
//int ret=avcodec_decode_video2(_videoCodecCtx,_videoFrame,&got_picture_ptr,packet);
int ret=0;
if(packet->size>0)
ret= avcodec_send_packet(_videoCodecCtx, packet);
while (ret>=0) {
ret = avcodec_receive_frame(_videoCodecCtx, _videoFrame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF){
//printf("Decode video Error 1.\n");
}else if (ret < 0) {
printf("Decode video Error 2.\n");
}else{
_videoFrame->linesize[3]=_videoFrame->height;
_frameCallback(_videoFrame->data,_videoFrame->linesize);
// uint8_t *outbuf[4];
// outbuf[0] = (uint8_t*)malloc(out_width*out_height);
// outbuf[1] = (uint8_t*)malloc(out_width*out_height>>2);
// outbuf[2] = (uint8_t*)malloc(out_width*out_height>>2);
// outbuf[3] = NULL;
// int outlinesize[4] = {out_width,out_width/2, out_width/2, 0};
// if(_videoSwsCxt!=NULL)
// {
// int result= sws_scale(_videoSwsCxt, (const unsigned char* const*)_videoFrame->data, _videoFrame->linesize, 0, _videoFrame->height,
// outbuf, outlinesize);
// if(result>0&&_frameCallback!=NULL)
// {
// _frameCallback(outbuf,outlinesize);
// }
// }
// uint8_t *outbuf[4];
// outbuf[0] = (uint8_t*)malloc(_videoW*_videoH);
// outbuf[1] = (uint8_t*)malloc(_videoW*_videoH>>2);
// outbuf[2] = (uint8_t*)malloc(_videoW*_videoH>>2);
// outbuf[3] = NULL;
// int outlinesize[4] = {_videoW,_videoW/2, _videoW/2, 0};
// int *linesize=_videoFrame->linesize;
// uint8_t **data=_videoFrame->data;
// int videoW=_videoFrame->width;
// int videoH=_videoFrame->height;
// int result= libyuv::I420Scale(data[0],linesize[0],data[1],linesize[1],data[2],linesize[2],videoW,videoH,
// outbuf[0],outlinesize[0],outbuf[1],outlinesize[1],outbuf[2],outlinesize[2],_videoW,_videoH,
// libyuv::FilterMode::kFilterNone);
//
// if(result>=0&&_frameCallback!=NULL)
// {
// _frameCallback(outbuf,outlinesize);
// }
// free(outbuf[0]);
// free(outbuf[1]);
// free(outbuf[2]);
// free(outbuf[3]);
}
}
//}
// int ret=avcodec_decode_video2(_videoCodecCtx,_videoFrame,&got_picture_ptr,packet);
// if(ret>0&&got_picture_ptr){
// //av_frame_free(&_videoFrame);
// //emit SDLRender(NULL);
// }
// av_free_packet(packet);
}
void DecodeVideoThread::stop(){
_run=false;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。