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