407 lines
14 KiB
C++
407 lines
14 KiB
C++
|
#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;
|
|||
|
qDebug() << args << endl;
|
|||
|
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);
|
|||
|
}
|