ホーム » 2015 (ページ 9)
年別アーカイブ: 2015
ニュース配信Twitterは05:00,Facebookは14:00-16:00
Internet Watchの記事「ニュース記事の配信時刻、Twitterは朝5時台、Facebookは午後2~4時台が拡散しやすいとの調査結果」 という記事をみて、Twitter連動で動かしている処理の時間を変更してみた。
この記事を参考に、0:500 (朝イチのニュースを見る人向け)、11:00(昼休み向け)、16:00(After5向け)、19:00(夜のくつろぎタイム向け)? に更新をかけるようにしてみた。
HTTP Live Streaming
学校内での積極的な研究活動に助成を行うための校長裁量経費にて、 昨年度は動画配信環境の整備の予算をわずかながらであったが、 利用することができた。 撮影用の高画質のビデオカメラを導入したけど、 実際は動画配信ができなければ、あまり意味がなくなってしまう。 本当は、Mac pro を導入し、動画編集・ストリーミング配信用動画形式変換などを 目指す予定だったけど、予算も無いのでまずはフリーの環境にて構築。
校内WiFiが整備されたけど、不容易なトラブルを防ぐためにも、HTTPベースの 通信に限られていることから、RTSPなどのストリーミングプロトコルを使った 実装は面白く無いので、ひとまずの実験は、AppleのHTTP Live Streamingにて実験。
この方式では、動画データに加え一定間隔毎のヒント情報を保存しておくことで、 動画をHTTPにて配信する。そのヒント情報の生成には今回、フリーのffmpegを 使用。
(( ffmpegのインストール )) # aptitude install ffmpeg
ffmpegの使い方は機能が豊富すぎて、Webに転がっている記事を参考に、 色々試すがなかなかうまくいかない。 最終的に成功したのが、以下のコマンド。
(( ヒント情報の生成 )) $ ffmpeg -i 動画.mp4 -f segment -segment_format mpegts -segment_time 10 -segment_list 動画.m3u8 動画-%03d.ts
ただし、Appleの技術を使っているためか、パソコンのSafariでしか動画再生が うまくいかない。 また、スマホ・タブレットでも、高画質動画が元のためか iOS Safari でも 再生に失敗する。 もう少し、データ形式の変換の実験が必要そうだ….
参考…
参考までに、成功した動画を置いておく。(PC Safariのみ)
また肖像権などの問題への心配から、学内閲覧のみのURLにて公開します。
2015年6月21日(第428回)
- 中間試験の話
- プレゼンテーションの話
- 父の日の話
- ジャズバー歴史 1杯目「お札の人物こぼれ話」
- 新コーナーが始まりました!コーナーMCは手嶋先生です。
担当:松島(4C)、植村(2E)、川﨑(2EI)、中村(教員)
仮想関数とグラフィックス
前回の授業で仮想関数の話をしたので、 演習と課題に取組む。
最初に、学科によってはグラフィックスを使う機会も少ないし、 演習もかなり以前だと思われるので、GrWinの使い方を思い出してもらうための資料を配布。
仮想関数とグラフィックス処理
次に、前回の授業の後半で説明した、グラフィックスを扱う仮想関数のサンプルプログラムを示し、 その説明を行う。
このサンプルプログラムでは、グラフィックスを使うということで、 GrWinクラスを作り、コンストラクタでウィンドウの初期化処理、 デストラクタでウィンドウの閉じる処理を記載してある。
class GrWin { privete: int width , height ; public: GrWin( int , int ) ; ~GrWin() ; } ; // コンストラクタでウィンドウを開く処理 GrWin::GrWin( int w , int h ) : width( w ) , height( h ) { GWopen( 0 ) ; // 略: PDF資料をみてください } // デストラクタでウィンドウを閉じる処理 GrWin::~GrWin() { GWquit() ; } void main() { GrWin gr( 640 , 480 ) ; // 描画処理 }
次に、図形を描くクラス(Figure)を考える。 このクラスから四角(FigureBox)と、円(FigureCircle)を派生させる。
// 図形のクラス(純粋仮想基底クラス) class Figure { public: virtual void draw( int , int ) = 0 ; } ; // 四角を描く図形クラス class FigureBox : public Figure { private: int width , height ; public: FigureBox( int w , int h ) : width( w ) , height( h ) {} virtual void draw( int , int ) ; } ; virtual void FigureBox::draw( int x , int y ) { GWline( ... , ... , ... , ... ) ; // 略: PDF資料参照 } // 丸を描く図形クラス class FigureCircle : public Figure { private: int radius ; public: FigureCircle( int r ) : radius( r ) {} virtual void draw( int , int ) ; } ; virtual void FigureCircle::draw( int x , int y ) { // 略: PDF資料参照 for( double th = 0 ; th < 360 ; th += 5.0 ) { : } } void main() { Figure* array[3] = { new FIgureBox( 100 , 100 ) ; new FigureCircle( 150 ) ; new FigureBox( 50 , 100 ) ; } ; for( int i = 0 ; i < 3 ; i++ ) { array[ i ]->draw( 100 + 100 * i , 150 ) ; } }
2015年6月14日(第427回)
学生さんがテスト期間中につき、教員による収録でお送りしました。
- 新任教員紹介 環境都市工学科 樋口先生
- まるトレ傑作選 第100便 「寄せ書き」(平成27年4月26日放送)
ゲスト:環境都市工学科 樋口先生、国語科 伊勢先生
担当:中村(国語科教員、MC)、金田(機械工学科教員)、手嶋(社会科教員)、西(電子情報工学科教員、MIX)
2015年6月7日(第426回)
学生さんがテスト期間中につき、教員による収録でお送りしました。
- 新任教員紹介 国語科 伊勢先生
- まるトレ傑作選 第93便 「アクセント」後編(平成27年3月8日放送)
- 新コーナーの予告
ゲスト:国語科 伊勢先生
担当:中村(国語科教員、MC)、原口(英語科教員)、手嶋(社会科教員)、西(電子情報工学科教員、MIX)
Windows Update未適用が…
先週末の土日と、Kinectを使ったIT研向けの講習会を 3F演習室で行ったた。 この際に、Visual Studio をインストールする必要があって、 作業をしていたが、Windows Update の未適用が大量にあり、 実質2日間かけてアップデートを行った。
FEREC利用で最初の未適用…
原因は、WiFi設定で FEREC を使うようになっていると、 学生がWiFiで接続している時だけネットワークに繋がるため、 その作業時以外は、ネットワークにつながらず Update 未適用 になるのが一因とも思われる。
Windows Updateサーバが遮断された
最近は、有線LANでの接続状態にしてあるが、WiFiでUpdate 未適用の頃に、Microsoftのupdate用サーバ情報が更新されず、 Updateサーバを偽物と誤認し、ファイアウォールが接続の邪魔を して Windows Update が動かなかったと思われる。
一旦、ファイアウォールを止めて更新をかけたりしたら、 無事に更新がかかるようになった。 でも、100件以上の更新で、Updateの適用待ちやら再起動やらで、 実質2日仕事であった。
仮想関数と純粋仮想基底クラス
前々回の講義では派生と継承の説明にて、次のようなプログラムを説明した。
派生と継承の復習
// 基底クラス class Person { private: char name[ 20 ] ; int age ; public: Person( const char* s , int a ) { strcpy( name , s ) ; age = a ; } void print() { printf( "%s %d\n" , name , age ) ; } } ; // 派生クラス class Student : public Person { private: char dep[ 10 ] ; int grade ; public: Student( const char* s , int a , const char* d , int g ) : Person( s , a ) { strcpy( dep , d ) ; grade = g ; } void print() { // 継承でなくStudent版のprintを定義 Person::print() ; printf( "= %s %d\n" , dep , grade ) ; } } ; int main() { // 派生と継承の確認 Person tsaitoh( "tsaitoh" , 50 ) ; tsaitoh.print() ; Student naka( "naka" , 22 , "PS" , 2 ) ; naka.print() ; // Student版を実行 // 異なる型のデータをごちゃ混ぜにできないか? Person* table[2] ; table[0] = &tsaitoh ; table[1] = &naka ; for( int i = 0 ; i < 2 ; i++ ) { table[i]->print() ; } return 0 ; }
このプログラムのmain() では、tsaitohとnakaのデータを 表示させているが、tsaitohとnakaは、オマケの有る無しの違いはあっても、 元をたどれば、Person型。ごちゃまぜにできないだろうか?
int main() { : // 異なる型のデータをごちゃ混ぜにできないか? Person* table[2] ; table[0] = &tsaitoh ; table[1] = &naka ; for( int i = 0 ; i < 2 ; i++ ) { table[i]->print() ; } return 0 ; }
C++では、派生クラスは格下げして基底クラスのように振る舞うこともできる。 上記の例では、Studentのポインタ型である、&nakaは、 Personのポインタ型として振る舞うこともできる。
ただし、table[]に格納する時点で、Person型へのポインタなので、 table[i]->print() を呼び出しても、Personとして振る舞うため、 tsaitoh 50 / naka 22 が表示される。
仮想関数
上記のプログラムでは、Student型には、名前,年齢,所属,学年をすべて表示する Student::print() が宣言してある。 であれば、「naka 22」 ではなく、「naka 22 PS 2」と表示したくはならないか?
上記の例では、table[] に格納する段階で、格下げされているため、「naka 22」しか表示できない。 しかし、以下のように書き換えると、「naka 22 PS 2」と表示できる。
// 基底クラス class Person { private: char name[ 20 ] ; int age ; public: Person( const char* s , int a ) { strcpy( name , s ) ; age = a ; } virtual void print() { printf( "%s %d\n" , name , age ) ; } } ; // 派生クラス class Student : public Person { private: char dep[ 10 ] ; int grade ; public: Student( const char* s , int a , const char* d , int g ) : Person( s , a ) { strcpy( dep , d ) ; grade = g ; } virtual void print() { // 継承でなくStudent版のprintを定義 Person::print() ; printf( "= %s %d\n" , dep , grade ) ; } } ; int main() { Person tsaitoh( "tsaitoh" , 50 ) ; Student naka( "naka" , 22 , "PS" , 2 ) ; // 異なる型のデータをごちゃ混ぜにできないか? Person* table[2] ; table[0] = &tsaitoh ; table[1] = &naka ; for( int i = 0 ; i < 2 ; i++ ) { table[i]->print() ; } return 0 ; }
上記の例の用に、printメソッドに virtual 宣言を追加すると、 C++では、tsaitoh,naka のデータ宣言時に、データ種別情報が埋め込まれる。 この状態で、table[i]->print() を呼び出されると、 データ種別毎のprint()を呼び出してくれる。 (この実装では、前回授業の関数ポインタが使われている)
ここで、学生さんから、「table[] の宣言をStudentで書いたらどうなるの?」という 質問がでた。おもわず『良い質問ですねぇ〜』と池上彰ばりの返答をしてしまった。
Student* table[] ; table[0] = &tsaitoh ; // 文法エラー // 派生クラスは基底クラスにはなれるけど、 // 基底クラスが派生クラスになることはできない。 table[1] = &naka ;
純粋仮想基底クラス
// 純粋仮想基底クラス class Object { public: virtual void print() = 0 ; // 中身の無い純粋基底クラスを記述しない時の書き方。 } ; // 整数データの派生クラス class IntObject : public Object { private: int data ; public: IntObject( int x ) { data = x ; } virtual void print() { printf( "%d\n" , data ) ; } } ; // 文字列の派生クラス class StringObject : public Object { private: char data[ 100 ] ; public: StringObject( const char* s ) { strcpy( data , s ) ; } virtual void print() { printf( "%s\n" , data ) ; } } ; // 実数の派生クラス class DoubleObject : public Object { private: double data ; public: DoubleObject( double x ) { data = x ; } virtual void print() { printf( "%lf\n" , data ) ; } } ; // 動作確認 int main() { Object* data[3] = { new IntObject( 123 ) , new StringObject( "abc" ) , new DoubleObject( 1.23 ) , } ; for( int i = 0 ; i < 3 ; i++ ) { data[i]->print() ; } return 0 ; } ;
この書き方では、data[]には、整数、文字列、実数という異なるデータが入っているが、 Objectという純粋仮想基底クラスを通して、共通な型のように扱えるようになる。 そして、data[i]->print() では、各型の仮想関数が呼び出されるため、 「123 abc 1.23」 が表示される。
ここで、Object の様な一見すると中身が何もないクラスを宣言し、 このクラスから様々な派生クラスを用いるプログラムテクニックは、 広く利用され、Objectのような基底クラスは、純粋仮想基底クラスなどと呼ばれる。
関数ポインタと仮想関数への導入
派生と継承の基本の説明をしてきたので、次に説明する予定の仮想関数の導入として、 実装のために使われている関数ポインタを紹介。
関数ポインタ
関数ポインタとは、関数へのポインタであり、ポインタを変更することで、 処理を切り替えるために使われる。 まずは、動作説明の簡単なプログラムを紹介。
int add( int x , int y ) { // 加算関数 return x + y ; } int mul( int x , int y ) { // 乗算関数 return x * y ; } void main() { int (*f)(int,int) ; // int×2引数、返り値intの関数へのポインタ f = add ; printf( "%d" , (*f)( 2 , 3 ) ) ; // 5を表示 f = mul ; printf( "%d" , (*f)( 2 , 3 ) ) ; // 6を表示 }
関数ポインタを利用すれば、異なるデータに対する処理を、 汎用性高く作ることも可能となる。 例えば以下の vmax() 関数は、自分で用意した大小を比較するだけの関数を渡し、 それ以外の最大値を求めるための処理を行う。 このため、他のデータの最大値を求めたい場合でも、最大値を求める処理を すべて記載するのではなく、対象データの比較関数だけを記述すれば良い。
int intcmp( int* x , int* y ) { // 整数比較関数 if ( *x > *y ) return 1 ; else if ( *x < *y ) return -1 ; else return 0 ; } int vmax( void* array , // 配列先頭アドレス int size , // 配列データ件数 int sizeofdata , // 1件あたりのbyte数 int(*f)( void*,void* ) ) { // 比較関数 int i , max = 0 ; for( i = 0 ; i < size ; i++ ) if ( (*f)( array + max * sizeofdata , array + i * sizeofdata ) ) max = i ; return max ; } int idata[ 4 ] = { 11 , 33 , 22 , 44 } ; char sdata[ 4 ][ 4 ] = { "ab" , "bc" , "aa" , "c" } ; void main() { int m ; // intcmp関数を使って、idata から最大値を探す m = vmax( idata , 4 , sizeof(int) , intcmp ) ; printf( "%d" , idata[ m ] ) ; // strcmp関数を使って、sdata から最大値を探す m = vmax( sdata , 4 , sizeof(sdata[0]) , strcmp ) ; printf( "%s" , sdata[ m ] ) ; }