動画再生ライブラリ。ベータ版。5


色々と更なる構造を練ったりしてみましたがピンと来るものが浮かばず。
こればかりに固着する訳にもいかないのでムービーライブラリは一旦筆を置くことにします。
現時点でちゃんと動作してるというのもありますので。


ライブラリとして公開するとなると
動画データの作成手順やらサンプル動画やらと別の手間が出てしまうので
手が空くまではこのエントリーでソースのみ公開とします。


実機でしかまともに動かないです。
WinDS PRO からの iDeaS にて動作することを確認しました
プラグイン導入済みの iDeaS ではちゃんと動作するということなのでしょうか?)。


WinDS PRO
http://windspro.forum777.com/


こちらは動作イメージです。


次は画面合成辺りを書いてこうかと思います。


暫定版ソース


movie.h

/*---------------------------------------------------------------------------------
	
	movie library header
	
	version 0.01 beta
	Jun 14, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#ifndef _MOVIE_H_
#define _MOVIE_H_


#include <nds/ndstypes.h>


#ifdef __cplusplus
extern "C" {
#endif


//動画再生ライブラリを初期化します。
void movie_Init(void);

//動画を再生します。
//引数には描画先アドレス、動画ファイル名、繰り返し再生の有無、を指定します。
//
//動画データのファイル書式は以下のとおりになります。
// NDSスクリーンサイズ(256*192)のNDS画像形式の16bitBMPデータ1つを1シーンとした、
// 複数のシーンデータを1ファイルにまとめたもの。
//
//戻り値にはエラー情報が返ります。エラーがあった場合は動画再生は行われません。
// 0:エラー無し, -1:FAT初期化エラー, -2:ファイルオープンエラー, -3:ファイル書式エラー
int movie_Play(u16 *buf, const char *filename, bool loop);

//動画を停止します。
void movie_Stop(void);

//動画の再生状態を確認します。
// 0:停止中, 1:再生中
int movie_GetAct(void);


#ifdef __cplusplus
}
#endif

#endif	//_MOVIE_H_


movie.c

/*---------------------------------------------------------------------------------
	
	movie library routine
	
	version 0.01 beta
	Jun 14, 2010
	
	By REGEKATSU
	
---------------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fat.h>
#include <nds/interrupts.h>
#include <nds/timers.h>
#include <nds/arm9/video.h>
#include "movie.h"


//動画データにおける1シーンのデータサイズ
const u32 BG_BMP16_256x192 = {SCREEN_WIDTH * SCREEN_HEIGHT * sizeof(u16)};


typedef enum{
	MOVIE_STOP = 0x00, 
	MOVIE_PLAY
}MOVIE_ACT;


typedef struct{
	
	int act;            //動画再生状態
	u32 timer;          //タイマー割り込み用カウンタ
	u16 *buf;           //動画出力先アドレス
	
	char filename[256]; //動画データファイルパス
	FILE *fp;           //動画データファイルポインタ
	u32 scenes;         //動画データシーン数(コマ数)
	bool loop;          //繰り返し再生の有無
	
}MovieStatus;


static MovieStatus st_movie;


void movie_Timer1Handler(void);
void movie_Timer2Handler(void);
void movie_Update(void);


//---------------------------------------------------------------------------------
void movie_Init(void){
//---------------------------------------------------------------------------------
	
	//内部変数の初期化。
	
	memset(&st_movie, 0, sizeof(st_movie));
	
	
	//タイマー割り込みを使って動画再生を実現する。
	//タイマー1, 2を使い、1秒間に15回、割り込みを発生させる。
	//これにより、秒間15コマの動画再生を行う。
	
	TIMER_DATA(1) = TIMER_FREQ_256(15);
	TIMER_CR(1)  = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_DIV_256;
	irqSet(IRQ_TIMER(1), movie_Timer1Handler);
	
	TIMER_DATA(2) = TIMER_FREQ_256(15);
	TIMER_CR(2)  = TIMER_ENABLE | TIMER_IRQ_REQ | TIMER_DIV_256;
	irqSet(IRQ_TIMER(2), movie_Timer2Handler);
	
	
}

//---------------------------------------------------------------------------------
void movie_Timer1Handler(void){
//---------------------------------------------------------------------------------
	
	st_movie.timer++;
	
}

//---------------------------------------------------------------------------------
void movie_Timer2Handler(void){
//---------------------------------------------------------------------------------
	
	//動画再生の更新処理を行う。
	
	movie_Update();
	
}

//---------------------------------------------------------------------------------
int movie_Play(u16 *buf, const char *filename, bool loop){
//---------------------------------------------------------------------------------
	
	fpos_t size = 0;
	
	
	//状態を停止中に設定する。
	
	st_movie.act = MOVIE_STOP;
	
	
	//動画再生情報を内部変数にセットする。
	
	st_movie.buf = buf;
	strcpy(st_movie.filename, filename);
	st_movie.loop = loop;
	
	
	//DLDIパッチが適用されているか確認する。
	//DLDIパッチ未適用の場合、-1:FAT初期化エラー を返す。
	
	//一般的なカードサイズを超えてしまう場合Makeが通らないので
	//外部にデータを持たすことで対処している。
	
	if(fatInitDefault() == false) return -1;
	
	
	//動画データを確認する。
	//動画データが確認(オープン)出来なかった場合、-2:ファイルオープンエラー を返す。
	
	if((st_movie.fp = fopen(st_movie.filename, "rb")) == NULL) { fclose(st_movie.fp); return -2; }
	
	
	//動画データのファイルサイズを取得して、サイズからファイル書式が正しいものかどうか確認する。
	//動画データのファイル書式が正しくなかった場合、-3:ファイル書式エラー を返す。
	
	//動画データのファイル書式:
	// NDSスクリーンサイズ(256*192)のNDS画像形式の16bitBMPデータ1つを1シーンとした、
	// 複数のシーンデータを1ファイルにまとめたもの。
	
	//動画データのシーン総数割り出し:
	// 動画データファイルサイズ÷動画1シーンサイズ(256×192×2)=動画シーン総数
	
	fseek(st_movie.fp, 0, SEEK_END); 
	fgetpos(st_movie.fp, &size);
	
	if(size % BG_BMP16_256x192 != 0) { fclose(st_movie.fp); return -3; }
	st_movie.scenes = size / BG_BMP16_256x192;
	
	
	//全てのエラーチェックに問題が無ければ、
	//タイマー割り込みを有効して、再生状態を再生中に設定する。
	
	st_movie.timer = 0;
	
	irqEnable(IRQ_TIMER(1));
	irqEnable(IRQ_TIMER(2));
	
	st_movie.act = MOVIE_PLAY;
	
	return 0;
	
	
}

//---------------------------------------------------------------------------------
void movie_Update(void){
//---------------------------------------------------------------------------------
	
	//再生中以外の状態で再生処理を実行しない。
	
	if(st_movie.act != MOVIE_PLAY) return;
	
	
	if(st_movie.timer < st_movie.scenes - 1){
		
		//シーンデータを順に(タイマー割り込み毎に)、次のシーンデータが無くなるまで
		//1シーンづつ動画データの読込・描画を行う。
		
		fseek(st_movie.fp, st_movie.timer * BG_BMP16_256x192, SEEK_SET);
		fread((u16 *)st_movie.buf, BG_BMP16_256x192 / 2, sizeof(u16), st_movie.fp);
		
		
	}else{
		
		//次のシーンデータが無くなった場合。
		
		if(st_movie.loop == true){
			
			//繰り返し再生有りならタイマーを無効にせず、タイマー値をリセットする(シーンデータ頭出し→順次再生へ)。
			st_movie.timer = 0;
			
		}else{
			
			//繰り返し再生無しならタイマーを無効にして、動画再生処理を停止する。
			movie_Stop();
			
		}
		
		
	}
	
}

//---------------------------------------------------------------------------------
void movie_Stop(void){
//---------------------------------------------------------------------------------
	
	//既に停止状態である場合、停止処理を実行しない。
	
	if(st_movie.act == MOVIE_STOP) return;
	
	
	//動画データファイルをクローズして、タイマー割り込みを無効にする。また、再生状態も停止にする。
	
	fclose(st_movie.fp);
	irqDisable(IRQ_TIMER(1));
	irqDisable(IRQ_TIMER(2));
	st_movie.timer = 0;
	
	st_movie.act = MOVIE_STOP;
	
	
}

//---------------------------------------------------------------------------------
int movie_GetAct(void){
//---------------------------------------------------------------------------------
	
	return st_movie.act;
	
}

//---------------------------------------------------------------------------------