qt/LedOK/wProgramManager/wEditProgram/wElement/emovieattr.cpp
2022-01-20 10:08:17 +08:00

407 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
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);
}