1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

LED-Movie-Playerの音楽無し(zero対応)

Posted at

LED-Movie-Playerの音楽無し(zero対応)

「つくみ島だより」を参考に実行してみたんですが、USBオーディオで躓いて実行エラーとなるので、音楽コードをカットしました。
https://blog.tsukumijima.net/article/ledmatrix-movie/

led-movie-player.cc

#include <iostream>
#include <stdio.h>
#include <zconf.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <unistd.h>
#include <chrono>
#include <string>
#include "led-matrix.h"
#include "graphics.h"
#include "gpio.h"
#include <sys/types.h>
#include <sys/stat.h>


using namespace std; 
using namespace rgb_matrix;

// LEDマトリクスで動画を再生する関数
// 引数1: 動画のファイル名
// 引数2: 個々のLEDパネルの縦幅
// 引数3: 個々のLEDパネルの横幅
// 引数4: 直列に繋いでいるLEDパネルの数
// 引数5: 並列に繋いでいるLEDパネルの数

int play(std::string movie_file , int rows, int cols, int chain, int parallel){

    // LEDパネルのパラメータをOptionsに設定
    RGBMatrix::Options options;
    options.rows = rows;
    options.cols = cols;
    options.chain_length = chain;
    options.parallel = parallel;
    // ハードウェアパルス生成を無効にする
    // この値を false にしてハードウェアパルス生成を有効にする場合、
    // ラズパイに載っている音声モジュールを無効にする必要がある
    // この値を true にしてハードウェアパルス生成を無効にする場合、
    // 画面にちらつきが出る事があるので非推奨らしい
    options.disable_hardware_pulsing = false;

    // GPIOを初期化
    GPIO io;

    if (!io.Init())
        return 1;

    // LEDマトリクスの初期化
    RGBMatrix *matrix = new RGBMatrix(&io, options); // RGBMatrixを初期化
    matrix->set_luminance_correct(true);
    matrix->SetBrightness(100);
    matrix->SetPWMBits(11);
    FrameCanvas *canvas = matrix->CreateFrameCanvas(); // 描画Canvasを初期化
    const int width = canvas->width();
    const int height = canvas->height();

    // 動画の読み込み
    cv::Mat src_img;
    cv::Mat dst_img(height, width, src_img.type());
    cv::VideoCapture cap(movie_file.c_str()); // VideoCaptureを初期化

    auto fps = cap.get(CV_CAP_PROP_FPS); // 動画のfpsを取得
    long fps_ustime = 1000000.0 / (double)fps + 0.5;

    const auto hoseicount = (int)fps * 10;
    auto hcnt = 0;
 
    // 動画を再生する
    auto frame_cnt = cap.get(CV_CAP_PROP_FRAME_COUNT) - 1; // Magic!!!
    auto start = std::chrono::system_clock::now();

    // 1フレームごとに処理
    while (true){

        auto fpos = cap.get(CV_CAP_PROP_POS_FRAMES);
        // fposが総フレーム数を超えたら再生を終了する
        if(!(fpos < frame_cnt)){
            std::wcout << "    Stoping Play the Movie." << std::endl;
            break;
        }

        // フレームを取得(Capture)
        cap >> src_img;

        // LEDマトリクスに描画
        auto pos = cap.get(CV_CAP_PROP_POS_MSEC);
        auto r = (double) height / src_img.rows;
        auto w = (int) (src_img.cols * r);
        auto d = (width - w) / 2;
        cv::resize(src_img, dst_img, cv::Size(w, height), cv::INTER_AREA); // LEDマトリクスのサイズに合わせて取得したフレームをリサイズする
        for (int y = 0; y < height; y++){
            for (int x = 0; x < w; x++){
                cv::Vec3b bgr = dst_img.at<cv::Vec3b>(y, x);
                canvas->SetPixel(x + d, y, bgr[2], bgr[1], bgr[0]); // 1ピクセルごとに描画
            }
        }

        // 同期を取る
        matrix->SwapOnVSync(canvas);
        auto end = std::chrono::system_clock::now();

        auto delaytime = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();

        auto delaycount = pos * 1000 - delaytime;
        if (delaycount > 0) {
            usleep(delaycount);
        }
    }

    // 終了処理

    matrix->Clear();
    delete matrix;

}

// エントリーポイント

int main(int argc, char *argv[]){

    int cols; // 個々のLEDパネルの横幅
    int rows; // 個々のLEDパネルの縦幅
    int chain; // 直列に繋いでいるLEDパネルの数
    int parallel; // 並列に繋いでいるLEDパネルの数
    int loop; // ループ回数
    std::string loopstr; // 諸問題で文字列型のループ回数
    int loopflg; // ループフラグ
    std::string version = "2.3"; // バージョン
    std::string file; // ファイル(拡張子なし)
    struct stat st;

    // 引数確認
    // 変数argvは文字列なのでatoiでint型に変換しておく

    if (argc == 2){ // 引数が3個(コマンド名と動画ファイル名指定のみ)

        // デフォルト値で再生
        file = argv[1];
        loopstr = "none";

        cols = 64; // 個々のLEDパネルの横幅・適宜変更してください
        rows = 32; // 個々のLEDパネルの縦幅・適宜変更してください
        chain = 1; // 直列に繋いでいるLEDパネルの数・適宜変更してください
        parallel = 1; // 並列に繋いでいるLEDパネルの数・適宜変更してください

    } else if (argc == 3){ // 引数が3個(コマンド名と動画ファイル名とループ指定のみ)

        // デフォルト値で再生
        file = argv[1];
        loop = atoi( argv[2] );
        loopstr = argv[2]; //0が入るとNULLと判断されてしまうため敢えて文字型

        cols = 64; // 個々のLEDパネルの横幅・適宜変更してください
        rows = 32; // 個々のLEDパネルの縦幅・適宜変更してください
        chain = 1; // 直列に繋いでいるLEDパネルの数・適宜変更してください
        parallel = 1; // 並列に繋いでいるLEDパネルの数・適宜変更してください

    } else if (argc == 7){ // 引数が6個(LEDパネルの幅・高さ・個数等も指定)

        // 指定サイズで再生
        file = argv[1];
        loop = atoi( argv[2] );
        loopstr = argv[2]; // 0が入るとNULLと判断されてしまうため文字型にする
        cols = atoi( argv[3] );
        rows = atoi( argv[4] );
        chain = atoi( argv[5] );
        parallel = atoi( argv[6] );

    } else { // それ以外はエラー吐いて終了

        std::wcout << "    " << std::endl;
        std::wcout << "---------------------------------------------------" << std::endl;
        std::wcout << "  Error: Argument is missing or too many." << std::endl;
        std::wcout << "  Usage: 1: sudo led-movie-player [File name (no extension)]" << std::endl;
        std::wcout << "            ... Play" << std::endl;
        std::wcout << "         2: sudo led-movie-player [File name (no extension)] 0" << std::endl;
        std::wcout << "            ... Play (Infinite loop)" << std::endl;
        std::wcout << "         3: sudo led-movie-player [File name (no extension)] [Number of loops]" << std::endl;
        std::wcout << "            ... Play (Specified number of loops)" << std::endl;
        std::wcout << "         4: sudo led-movie-player [File name (no extension)] [Number of loops]" << std::endl;
        std::wcout << "                 [LED panel vertical width] [LED panel horizontal width]" << std::endl;
        std::wcout << "                 [Chain LED panels] [Parallel LED panels]" << std::endl;
        std::wcout << "            ... Play (Specify all arguments)" << std::endl;
        std::wcout << "    " << std::endl;
        std::wcout << "  Please retry... m(__)m" << std::endl;
        std::wcout << "---------------------------------------------------" << std::endl;
        std::wcout << "    " << std::endl;
        return 1;
    }

    int panelwidth = cols * chain ; // LEDパネルの横幅の合計
    int panelheight = rows * parallel ; // LEDパネルの縦幅の合計

    // 検索ディレクトリ・適宜変更してください
    std::string path = "/home/pi/movieplayer/";

    // 再生するファイルを検索して代入
    std::string movie_file = path + file + ".mp4"; // 動画ファイル

    // sudoで実行されてなかったら(Rootでないなら)エラー吐いて終了
    if (geteuid() != 0){
        std::wcout << "    " << std::endl;
        std::wcout << "---------------------------------------------------" << std::endl;
        std::wcout << "  Error: It must be run with Root privileges." << std::endl;
        std::wcout << "  Please add 'sudo' at the beginning" << std::endl;
        std::wcout << "  of the command and retry... m(__)m." << std::endl;
        std::wcout << "---------------------------------------------------" << std::endl;
        std::wcout << "    " << std::endl;
        return 1;
    }

    // ファイルがなかったらエラー吐いて終了
        if (stat(movie_file.c_str(), &st) != 0){
        std::wcout << "    " << std::endl;
        std::wcout << "---------------------------------------------------" << std::endl;
        std::wcout << "  Error: Specified file Not found." << std::endl;
        std::wcout << "  Please retry... m(__)m" << std::endl;
        std::wcout << "---------------------------------------------------" << std::endl;
        std::wcout << "    " << std::endl;
        return 1;
    }

    // ループ判別
    if (loopstr == "none"){ // ループ再生ではないとき
        loopflg = 0;
    } else if (loop == 0){ // 無限ループ
        loopflg = 1;
    } else if (loop >= 1){ // 有限ループ
        loopflg = 2;
    } else {
        loopflg = 0; //パラメータ変だったら取りあえず一回だけ
    }

    // 表示部分

    std::wcout.imbue(std::locale("en_GB.UTF-8"));
    std::wcout << "    " << std::endl;
    std::wcout << "---------------------------------------------------" << std::endl;
    std::wcout << "               LED-Movie-Player v" << version.c_str() << std::endl;
    std::wcout << "---------------------------------------------------" << std::endl;
    std::wcout << "    Chain LED Panels    : " << chain << std::endl;
    std::wcout << "    Parallel LED Panels : " << parallel << std::endl;
    std::wcout << "    One LED Panel Size  : " << cols << "x" << rows << std::endl;
    std::wcout << "    All LED Panel Sizes : " << panelwidth << "x" << panelheight << std::endl;
    std::wcout << "    " << std::endl;
    if (loopflg == 0){
        std::wcout << "    Press Ctrl + C to stop the movie." << std::endl;
    } else if (loopflg == 1 || loopflg == 2){
        std::wcout << "    If you want to stop loop, Press Ctrl + C." << std::endl;
    }
    std::wcout << "---------------------------------------------------" << std::endl;

    if (loopflg == 0){ // ループ再生しない

        // 表示
        std::wcout << "    Start playing movie..." << std::endl;
        std::wcout << "    " << std::endl;
        std::wcout << "    Now playing..." << std::endl;
        std::wcout << "---------------------------------------------------" << std::endl;

        // 再生を実行
        int result = play(movie_file, rows, cols, chain, parallel);

        // 終了
        std::wcout << "    See You!!" << std::endl;
    
    } else if (loopflg == 1){ // 無限ループ

        while (1){ // 無限ループ実行

            // 表示
            std::wcout << "    Start playing movie..." << std::endl;
            std::wcout << "    " << std::endl;
            std::wcout << "    Now Playing..." << std::endl;
            std::wcout << "---------------------------------------------------" << std::endl;

            // 再生実行
            int result = play(movie_file, rows, cols, chain, parallel);

            // 少し待つ
            std::wcout << "    Now looping..." << std::endl;
            std::wcout << "---------------------------------------------------" << std::endl;
            int second = 300000;
            usleep(second);
        }

    } else if (loopflg == 2){ // 有限ループ

        for (int i = 1; i <= loop; i++){ // ループ実行

            // 表示
            std::wcout << "    Start playing movie..." << std::endl;
            std::wcout << "    Number of loops   : " << loop << std::endl;
            std::wcout << "    Current loop count: "  << i << std::endl;
            std::wcout << "    " << std::endl;
            std::wcout << "    Now Playing..." << std::endl;
            std::wcout << "---------------------------------------------------" << std::endl;

            // 再生実行
            int result = play(movie_file, rows, cols, chain, parallel);

            if (i < loop){
                // 少し待つ
                std::wcout << "    Now looping..." << std::endl;
                std::wcout << "---------------------------------------------------" << std::endl;
                int second = 300000;
                usleep(second);
            } else if (i == loop){ // 最後のループなら
                std::wcout << "    See You!!" << std::endl;
            }
            
        }

    }

    std::wcout << "---------------------------------------------------" << std::endl;
    std::wcout << "    " << std::endl;

}




1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?