qt/LedOK/wProgramManager/wEditProgram/wElement/emovieattr.cpp

407 lines
14 KiB
C++
Raw Normal View History

2022-01-04 18:11:48 +08:00
#include "emovieattr.h"
#include "ui_emovieattr.h"
#include "emovie.h"
#include <QSettings>
#include <QThread>
extern "C"{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
}
eMovieAttr::eMovieAttr(const eMovie::Data &data, QWidget *parent) :
eAttr(parent),
ui(new Ui::eMovieAttr)
{
ui->setupUi(this);
ui->wFile ->setText (data.strRawName);
ui->wAspectRatioMode->setCurrentIndex(data.aspectRatioMode);
ui->wPlayDuration ->setValue (data.playDuration);
ui->wPlayTimes ->setValue (data.playTimes);
m_strOldSuiCaiFile=data.name;
m_strOldSuiCaiPath=data.path;
connect(ui->wAspectRatioMode, SIGNAL(currentIndexChanged(int)), this, SLOT(onAttrChanged()));
connect(ui->wPlayDuration, SIGNAL(valueChanged(int)), this, SLOT(onAttrChanged()));
connect(ui->wPlayTimes, SIGNAL(valueChanged(int)), this, SLOT(onAttrChanged()));
connect(ui->bnSelectFile, SIGNAL(clicked(bool)), this, SLOT(onSelectFile()));
ui->label_8->setVisible(false);
ui->wAspectRatioMode->setVisible(false);
}
eMovieAttr::~eMovieAttr()
{
delete ui;
}
void eMovieAttr::onSelectFile()
{
QString file = LoAppTools::getInstance()->selectFile(eMovie::filters(), this,true);
if(!file.isNull()) {
QString strOutFile=ConvertVideoFormatByFFmpeg(file);
QFileInfo outfi(strOutFile);
ui->wFile->setText(QFileInfo(file).fileName());
//alahover 20211115 alahover test sdl ffmpeg
// av_register_all(); /**初始化FFMPEG 调用了这个才能正常使用编码器和解码器**/
// avformat_network_init(); /**支持打开网络文件**/
// /**SDL初始化**/
// if (SDL_Init(SDL_INIT_AUDIO))
// {
// fprintf(stderr,"Could not initialize SDL - %s. \n", SDL_GetError());
// exit(1);
// }
// mPlayer = new VideoPlayer;
// myopenGLWidget=new glyuvwidget(this);
// myopenGLWidget->setGeometry(0,0,200,200);
// connect(mPlayer,SIGNAL(sigYuv_liuyi(uchar*,uint,uint)),this,SLOT(slotShowYuv_liuyi(uchar*,uint,uint)));
// mPlayer->stop(true); //如果在播放则先停止
// //这里需要再等待一段时间,目的是为了让解析视频的线程执行完成能够退出
// QEventLoop eventloop;
// QTimer::singleShot(100, &eventloop, SLOT(quit()));
// eventloop.exec();
// mPlayer->setFileName(file);//
// mPlayer->play();
// return;
int iSecs=GetVideoTimeRawSpan(strOutFile);
ui->wPlayDuration->setValue(iSecs);
emit sResChanged(strOutFile,file);
QString strOldFile=m_strOldSuiCaiPath+"/"+m_strOldSuiCaiFile;
QFile fileOld(strOldFile);
if(fileOld.exists())
{
fileOld.remove();
}
QFileInfo fi(strOutFile);
m_strOldSuiCaiFile = fi.fileName();
m_strOldSuiCaiPath = fi.absolutePath();
}
}
double eMovieAttr::GetVideoTimeRawSpan(QString strFilePathName)
{
AVFormatContext *pFormatCtx;
std::string str = strFilePathName.toStdString();
const char* filepath = str.c_str();
//char filepath[] = "G:\\taxiAd.mp4";
//初始化编解码库
av_register_all();//创建AVFormatContext对象与码流相关的结构。
pFormatCtx = avformat_alloc_context();
//初始化pFormatCtx结构
if (avformat_open_input(&pFormatCtx, filepath, nullptr, nullptr) != 0){
printf("Couldn't open input stream.\n");
return -1;
}
//获取音视频流数据信息
if (avformat_find_stream_info(pFormatCtx, nullptr) < 0){
printf("Couldn't find stream information.\n");
return -1;
}
//nb_streams视音频流的个数这里当查找到视频流时就中断了。
unsigned int iVideoStreamIndex=0;
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO){
iVideoStreamIndex=i;
}
}
AVStream *videoStream = pFormatCtx->streams[iVideoStreamIndex];
double totalSeconds = videoStream->duration * av_q2d(videoStream->time_base);
printf("totalSeconds = %lf\n", totalSeconds);
qreal iw= pFormatCtx->streams[iVideoStreamIndex]->codecpar->width ;
qreal ih=pFormatCtx->streams[iVideoStreamIndex]->codecpar->height ;
qDebug()<<""<<QString::number(iw);
qDebug()<<""<<QString::number(ih);
// if(iw!=0)
// m_display_aspect_ratio=ih/iw;
avformat_close_input(&pFormatCtx);
return totalSeconds;
}
void eMovieAttr::slotShowYuv_liuyi(uchar *ptr, uint width, uint height)
{
//if(!m_bStop)//如果点击停止按钮,则不再刷新图片
{
//ui->openGLWidget->slotShowYuv(ptr,width,height);
//myopenGLWidget->slotShowYuv(ptr,width,height);
}
}
QString eMovieAttr::getFileMd5(QString filePath)
{
QFile localFile(filePath);
if (!localFile.open(QFile::ReadOnly))
{
qDebug() << "file open error.";
return 0;
}
QCryptographicHash ch(QCryptographicHash::Md5);
quint64 totalBytes = 0;
quint64 bytesWritten = 0;
quint64 bytesToWrite = 0;
quint64 loadSize = 1024 * 4;
QByteArray buf;
totalBytes = localFile.size();
bytesToWrite = totalBytes;
while (1)
{
if(bytesToWrite > 0)
{
buf = localFile.read(qMin(bytesToWrite, loadSize));
ch.addData(buf);
bytesWritten += buf.length();
bytesToWrite -= buf.length();
buf.resize(0);
}
else
{
break;
}
if(bytesWritten == totalBytes)
{
break;
}
}
localFile.close();
QByteArray md5 = ch.result();
QString strRes="";
strRes.append(md5.toHex());
return strRes;
}
QString eMovieAttr::ConvertVideoFormatByFFmpeg(QString strFile)
{
QFileInfo tmpFile(strFile);
//QString strOutFileOnlyTitle=tmpFile.fileName().left(tmpFile.fileName().length()-tmpFile.suffix().length()-1);
QString file_full=strFile.replace(MACRO_DANYINFANXIEGAN, MACRO_DANYINXIEGAN);
QString strFileMD5=getFileMd5(file_full);
QString strOutFileOnlyTitle=strFileMD5;
QString strOutFilePathName=m_globalstrSavePath+MACRO_FENGEFU+strOutFileOnlyTitle+".mp4";
strOutFilePathName.replace(MACRO_DANYINFANXIEGAN, MACRO_DANYINXIEGAN);
int iReTryCount=0;
QDir dRoot;
QDir drr(m_globalstrSavePath);
if(!drr.exists())
{
while(!dRoot.mkdir(m_globalstrSavePath))
{
QThread::sleep(1);
iReTryCount++;
if(drr.exists())
break;
if(iReTryCount>10)
break;
}
}
QFileInfo tempFileInfo(strOutFilePathName);
if(tempFileInfo.exists())
{
return strOutFilePathName;
}
else {
LoAppConfig *cfg = LoAppConfig::getInstance();
QSettings *settings = new QSettings(cfg->OrganizationName(), cfg->ApplicationName());
if(settings->value("videoconvert").isValid())
{
if(settings->value("videoconvert").toBool())
{
process = new QProcess(nullptr);
connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(continueConvert(int,QProcess::ExitStatus)));
connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(outputCommand()));
connect(process,SIGNAL(readyReadStandardError()),this,SLOT(outputCommand()));
QStringList args;//=getArguments(strFile,"f://abc.mp4");
args<<"-y";
args<<"-i"<<file_full;
args<<"-vcodec"<<"h264";
QString strtempstrOutFilePathName=strOutFilePathName;
args<<strtempstrOutFilePathName;
m_pProgressConvertVideo = new LoEmptyDialog();
QString strAppPath=QApplication::applicationDirPath();
strAppPath.replace(MACRO_DANYINFANXIEGAN, MACRO_DANYINXIEGAN);
process->setWorkingDirectory(strAppPath);
process->start("ffmpeg",args);
//connect(m_pGetAskTimer,SIGNAL(timeout()),m_pProgressConvertVideo,SLOT(TimerOutUnlock()));
connect(this, SIGNAL(sigSetTipTextContent ( QString )), m_pProgressConvertVideo, SLOT( SetTipTextContent(QString)));
m_pProgressConvertVideo->lock(tr("Convert video"),tr("Success"),tr("Convert video")+tr("failed"));
// m_pGetAskTimer->start(3000);
m_pProgressConvertVideo->exec();
return strOutFilePathName;
}
else {
QFile::copy(strFile, strOutFilePathName);
return strOutFilePathName;
}
}
else {
QFile::copy(strFile, strOutFilePathName);
return strOutFilePathName;
}
}
}
QString eMovieAttr::ConvertVideoFormat(QString strFile)
{
QFileInfo tmpFile(strFile);
//QString strOutFileOnlyTitle=tmpFile.fileName().left(tmpFile.fileName().length()-tmpFile.suffix().length()-1);
QString file_full=strFile.replace(MACRO_DANYINFANXIEGAN, MACRO_DANYINXIEGAN);
QString strFileMD5=getFileMd5(file_full);
QString strOutFileOnlyTitle=strFileMD5;
QString strOutFilePathName=m_globalstrSavePath+MACRO_FENGEFU+strOutFileOnlyTitle+".mp4";
QFileInfo tempFileInfo(strOutFilePathName);
if(tempFileInfo.exists())
{
return strOutFilePathName;
}
else {
process = new QProcess(this);
connect(process,SIGNAL(finished(int,QProcess::ExitStatus)),this,SLOT(continueConvert(int,QProcess::ExitStatus)));
connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(outputCommand()));
connect(process,SIGNAL(readyReadStandardError()),this,SLOT(outputCommand()));
QStringList args;//=getArguments(strFile,"f://abc.mp4");
args<<"-y";
args<<"-i"<<strFile;
args<<"-vcodec"<<"h264";
args<<strOutFilePathName;
process->start("ffmpeg",args);
m_pProgressConvertVideo = new LoEmptyDialog();
//connect(m_pGetAskTimer,SIGNAL(timeout()),m_pProgressConvertVideo,SLOT(TimerOutUnlock()));
m_pProgressConvertVideo->lock(tr("Convert video"),tr("Success"),tr("Convert video")+tr("failed"));
// m_pGetAskTimer->start(3000);
m_pProgressConvertVideo->exec();
return strOutFilePathName;
}
}
void eMovieAttr::continueConvert(int i,QProcess::ExitStatus)
{
//int aa=i;
m_pProgressConvertVideo->unlock();
}
void eMovieAttr::outputCommand(){
QByteArray cmdoutput = process->readAllStandardOutput();
char *t=cmdoutput.data();
QString txtoutput=QString::fromLocal8Bit(t);
qDebug()<<txtoutput;
cmdoutput = process->readAllStandardError();
t=cmdoutput.data();
txtoutput=QString::fromLocal8Bit(t);
qDebug()<<txtoutput;
if(txtoutput.contains("Duration: "))
{
QString strDuration=txtoutput.mid(txtoutput.indexOf("Duration: ")+10,11)+"0";
qDebug()<<"Duration="<<strDuration;
QTime aa=QTime::fromString(strDuration,TIME_STRING_FORMAT);
QTime bb(0,0,0);
m_videoTimeLong=bb.secsTo(aa);
}
if(txtoutput.contains("time="))
{
QString strTime=txtoutput.mid(txtoutput.indexOf("time=")+5,11)+"0";
qDebug()<<"time="<<strTime;
QTime aa=QTime::fromString(strTime,TIME_STRING_FORMAT);
QTime bb(0,0,0);
int iJinDuTime=bb.secsTo(aa);
if(m_videoTimeLong>0)
{
int iJindu=iJinDuTime*100/m_videoTimeLong;
qDebug()<<"进度="<<iJindu;
QString strJindu=QString::number(iJindu)+"%";
emit sigSetTipTextContent(tr("Converting format")+strJindu);
}
}
}
QStringList eMovieAttr::getArguments(QString filepath,QString output){
QStringList args;
args << "-i" << filepath;
args << "-vcodec" <<"libx264";
// if(ui->comboBox_vcodec->currentIndex()!=2){
// args << "-vcodec" << ui->comboBox_vcodec->currentText();
// }
args << "-b:v" << "2000k";
// switch(ui->comboBox_videoQuality->currentIndex()){
// case 0:args << "-b:v" << "2000k";break;
// case 1:args << "-b:v" << "1000k";break;
// case 2:args << "-b:v" << "500k";break;
// case 3:args << "-b:v" << "250k";break;
// case 4:args << "-b:v" << ui->lineEdit_videoQuality->text();break;
// }
args << "-s" << "800x600";
// args << "-s" << ui->comboBox_videoScale->currentText();
// if(ui->checkBox_hasWatermark->isChecked()){
// args << "-vf" << tr("movie=%1[logo];[in][logo] overlay=%2:%3 [out]").arg(QFileInfo(ui->lineEdit_watermarkPath->text()).fileName())
// .arg(ui->lineEdit_watermark_x->text())
// .arg(ui->lineEdit_watermark_y->text());
// }
//args << "-acodec" << "libvo_aacenc";
args <<"-c:a aac";
// if(ui->comboBox_audioCodec->currentIndex()!=2)
// args << "-acodec" << ui->comboBox_audioCodec->currentText();
// args << "-b:a" << "64k";
// switch(ui->comboBox_audioQuality->currentIndex()){
// case 0:args << "-b:a" << "256k";break;
// case 1:args << "-b:a" << "192k";break;
// case 2:args << "-b:a" << "125k";break;
// case 3:args << "-b:a" << "96k";break;
// case 4:args << "-b:a" << ui->lineEdit_audioQuality->text();break;
// }
args << "-ac" << "2";
// args << "-ac" << QString::number(ui->comboBox_audioChannel->currentIndex()+1);
args << "-ar" <<"44100";
// args << "-ar" << ui->comboBox_audioRate->currentText();
args << "-y";
// QString output=ui->lineEdit_mainOutputPath->text()
// +filepath.right(filepath.count()-ui->lineEdit_mainSourcePath->text().count());
// output=output.left(output.count()-3)+ui->comboBox_convertTo->currentText();
QDir outputPath;outputPath.mkpath(QFileInfo(output).absolutePath());
args << output;
2022-01-20 10:08:17 +08:00
qDebug() << args;
2022-01-04 18:11:48 +08:00
return args;
}
void eMovieAttr::onAttrChanged()
{
eMovie::Data data;
data.aspectRatioMode = ui->wAspectRatioMode->currentIndex();
data.playDuration = ui->wPlayDuration->value();
data.playTimes = ui->wPlayTimes->value();
emit sAttrChanged(data);
}