Video module based on mplayer

Posted by chuspy on Wed, 29 Dec 2021 16:40:20 +0100

brief introduction

Mplayer is an open source multimedia player that can run in mainstream operating systems, such as LInux, Unix like, Windows, Mac OS. Mplayer is built on the command line interface. For the use of the command line, refer to: https://www.cnblogs.com/huangpeng1990/p/4364373.html
Here are some common command lines based on my project code

1. Play command

QString cmd = QString("mplayer -ac mad -slave -quiet -geometry 0:0 -zoom -x 400 -y 240 %1 &").arg(video_name);
process->start(cmd.toUtf8());	//Execute playback command
  • -AC mad: arm board operation
  • -slave: controlled by background command
  • -quiet: the background interface will not output miscellaneous information
  • -geometry 0:0: the upper left corner of the display interface is in coordinates (0, 0)
  • -zoom -x 400 -y 240: the length of the display interface is 400 and the width is 240
  • %1: Replace with file name and path to indicate the file to be played
  • &: indicates that Mplayer can run in the background (other operations can still be performed even if Mplayer is enabled)

2. Pause / resume playback

process->write("pause\n");	
  • If Mplayer is running, it will pause after executing this command
  • If Mplayer is suspended, it will resume operation after executing this command
  • \n: Each command needs to be marked with "\ n" at the end to indicate the end of the command

3. Fast forward video and backward video

process->write("seek -5\n");	//Fast forward 5 seconds
process->write("seek 5\n");		//Back off for 5 seconds

4. Adjust the volume

QString cmd = "volume " + QString::number(position) + " 1\n";	//"volume <value> [abs]"
  • If abs is not 0, set the value of value to the volume
  • If abs is 0, it is the value of increasing or decreasing the volume

Implementation steps

1. Initialization

VideoWindow::VideoWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::VideoWindow)
{
    ui->setupUi(this);
    //Allocate memory space to processes
    process = new QProcess(this);
    //The initial state of the player is off
    playstate = 0;
    //Initialize progress bar
    ui->slider_progress->setRange(0,100);
    ui->slider_progress->setValue(0);
    //Initialize volume bar
    ui->slider_volumn->setRange(0,100);
    ui->slider_volumn->setValue(20);
    //Initialization timer
    timer = new QTimer(this);
    QObject::connect(timer, &QTimer::timeout, this, &VideoWindow::timeout_slot);
    //Turn on the timer and start it every 1000ms
    timer->start(1000);
}

2. Set the "open file" button

//Open folder to add playback files
void VideoWindow::on_pushButton_openfile_clicked()
{
    QStringList video_list = QFileDialog::getOpenFileNames(this, "Select play file", "/home/gec", "video (*.mp4 *.avi *.mkv)");
    //Define an iterator and store it in video_ Take out the file in the list and put it into the listWidget
    QList<QString>::iterator video_iterator = video_list.begin();
    for( ; video_iterator != video_list.end(); video_iterator++)
        ui->listWidget->addItem(*video_iterator);
}

3. Set the "play" button

//Start playing video
void VideoWindow::on_pushButton_start_clicked()
{
    if(playstate == 1){
        //Close the currently playing video
        process->write("quit\n");
        //Cancels all communication with the process and kills the process, but does not execute exit() to reclaim its resources. The process cannot send the signal readyRead()
        process->close();
    }
    //Gets the name of the current file
    QString video_name = ui->listWidget->currentItem()->text();
    QString cmd = QString("mplayer -ac mad -slave -quiet -geometry 0:0 -zoom -x 400 -y 240 %1 &").arg(video_name);
    //Assign signal resources to processes
    QObject::connect(process, &QProcess::readyReadStandardOutput, this, &VideoWindow::read_standoutput_slot);
    //Start playing
    process->start(cmd.toUtf8());
    playstate = 1;
}

4. Set the pause button

//Pause, resume playback after pause
void VideoWindow::on_pushButton_pause_clicked()
{
    //If it is playing, let the timer pause to prevent the timer from sending signals all the time so that the video cannot be paused
    if(playstate == 1){
        playstate = 0;
        timer->stop();
    }
    else{
        playstate = 1;
        timer->start(1000);
    }
    process->write("pause\n");
}

5. Set the "play previous and next video" button

//Play previous video
void VideoWindow::on_pushButton_last_clicked()
{
    int last_low = ui->listWidget->currentRow() - 1;
    //If the current line is the first, the previous one cannot be played
    if(last_low == -1)
        return;
    //Change the current number of rows in listWidget
    ui->listWidget->setCurrentRow(last_low);
    QString video_name = ui->listWidget->currentItem()->text();
    //If it is currently playing, the playback of the current video will be cancelled
    if(playstate == 1){
        process->write("quit\n");
        process->close();
    }
    QString cmd = QString("mplayer -slave -ac mad -quiet -geometry 0:0 -zoom -x 400 -y 240 %1 &").arg(video_name);
    //Assign signal resources to processes
    QObject::connect(process, &QProcess::readyReadStandardOutput, this, &VideoWindow::read_standoutput_slot);
    //Start playing
    process->start(cmd.toUtf8());
    playstate = 1;
    //Make the key (next) effective
    ui->pushButton_next->setEnabled(true);
    //If it is currently the first line, the last key is invalid
    if(ui->listWidget->currentRow() == 0)
        ui->pushButton_last->setEnabled(false);
}

//Play next video
void VideoWindow::on_pushButton_next_clicked()
{
    int next_low = ui->listWidget->currentRow() + 1;
    qDebug() << ui->listWidget->count() << endl << ui->listWidget->currentRow();
    //If the current line is the last, the next video cannot be played
    if(next_low + 1 > ui->listWidget->count())
        return;
    //Change the current number of rows in listWidget
    ui->listWidget->setCurrentRow(next_low);
    QString video_name = ui->listWidget->currentItem()->text();
    //If it is currently playing, the playback of the current video will be cancelled
    if(playstate == 1){
        process->write("quit\n");
        process->close();
    }
    QString cmd = QString("mplayer -slave -ac mad -quiet -geometry 0:0 -zoom -x 400 -y 240 %1 &").arg(video_name);
    //Assign signal resources to processes
    QObject::connect(process, &QProcess::readyReadStandardOutput, this, &VideoWindow::read_standoutput_slot);
    //Start playing
    process->start(cmd.toUtf8());
    playstate = 1;
    //Make the last key effective
    ui->pushButton_last->setEnabled(true);
    //If the current is the last line, the key (next) is disabled
    if(ui->listWidget->currentRow() + 1 == ui->listWidget->count())
        ui->pushButton_next->setEnabled(false);
}

6. Change the playback bar in real time to display the playback progress

//What the timer does every second
void VideoWindow::timeout_slot()
{
    //Gets the total length of time in seconds
    process->write("get_time_length\n");
    //Gets the current time position in seconds
    process->write("get_time_pos\n");
    //Gets the percentage of the current playback progress
    process->write("get_percent_pos\n");
}

//Read data from standard output
void VideoWindow::read_standoutput_slot()
{
    if(process->canReadLine()){
        QString message(process->readLine());
        QStringList message_list = message.split("=");
        //Get total video length
        if(message_list[0] == "ANS_LENGTH")
            time_length = message_list[1].toDouble();
        //Gets the time of the current location
        else if(message_list[0] == "ANS_TIME_POSITION"){
            time_pos = message_list[1].toDouble();
            //Display time
            QString time_text;
            time_text = QString("%1%2:%3%4/%5%6:%7%8").
                    arg(QString::number(time_pos/60/10)).arg(QString::number(time_pos/60%10)).arg(QString::number(time_pos%60/10)).arg(QString::number(time_pos%60%10)).
                    arg(QString::number(time_length/60/10)).arg(QString::number(time_length/60%10)).arg(QString::number(time_length%60/10)).arg(QString::number(time_length%60%10));
            ui->label_time->setText(time_text);
        }
        //Gets the percentage of the current location
        else if(message_list[0] == "ANS_PERCENT_POSITION")
            //Set the range of progress bar: 0 ~ 100, so the value of percentage is the value
            ui->slider_progress->setValue(message_list[1].toUInt());
    }
}
  • The timer sends a signal to the slot function timeout every 1 second_ Slot(), execute "get_time_length\n", and the background will output the information of time length. Because "QObject:: connect (process, & qprocess:: readyreadstandardoutput, this, & videowindow:: read_standoutput_slot);" was executed before, After the background outputs the information, it sends a signal to the slot function read_standoutput_slot(), the slot function executes "qstring message (process - > readline())" to read the contents of the standard output and perform string processing to display the total video time. The other two commands "get_time_pos\n" and "get_percent_pos\n" get the playback progress in a similar way.

7. Manually change the playback progress

//Slide the progress bar to change the progress
void VideoWindow::on_slider_progress_sliderMoved(int position)
{
    if(playstate == 1){
        QString com = "seek " + QString::number(position) + " 1\n";
        process->write(com.toUtf8());
    }
}

8. Slide the volume bar to change the volume

void VideoWindow::on_slider_volumn_sliderMoved(int position)
{
    if(playstate == 1){
        QString cmd = "volume " + QString::number(position) + " 1\n";
        process->write(cmd.toUtf8());
    }
}

design sketch

Topics: Linux Qt ARM