マイコンのデバッグの際USART経由でコンソールにprintfと等しい出力をさせるためこんな書き方をしていました。

sprintf(buffer, "\r\nTime:%s", __TIME__); // sprintfで文字列バッファbufferに書式付きで出力
USARTPutString(buffer); // 文字列バッファbufferをUSARTで出力

これでもいいのですが、毎度デバッグ出力のたびに2行必要なのであまりスマートな記述方法ではないなと思いながらずっとこんな書き方をしてました(^^;A

ところが最近になって"可変長引数"という存在を知り、長年のモヤモヤが一気に解消に!

printfはconst char *と...という引数で定義されています。
const char *にあたる部分が書式や文字列にあたり、...が可変長引数に相当します。
この...(可変長引数)が今回の話のミソでして、コイツをうまく扱えばprintfのラッパーのような関数が作れるのでは?と考えました。

ぐぐってみるとたくさんヒットしました。
その中でvsprintfを使うという超お手軽な方法があることを知り、最終的に下のようなprintのラッパーが完成しました。

#include <stdio.h>
#include <stdarg.h>

int USARTPrintf(const char *fmt, ...){
static char buffer[100];
int ret;
va_list ap;

va_start(ap, fmt);
ret = vsprintf(buffer, fmt, ap);
USARTPutString(buffer);
va_end(ap);

return ret;
}


va_listは可変長引数を扱うための構造体をつくり、va_start、va_end等は可変長引数を扱うために必要なマクロです。(詳しいことはわかりません汗)
vsprintfは可変長引数を扱うための構造体をそのまま取り込み、printfのような処理をしてバッファに書式付きで出力してくれます。

これでUSARTPrintf("\r\nTime:%s", __TIME__);などとすると一行記述でprintfと同等の結果が得られました。

しかしprintfという名前がどうしても使いたくてもうちょっとかっこよくするためにdebugという構造体をつくり、その中でprintfという関数の型を定義し上で作ったUSARTPrintfをアサインさせて予約語の重複を回避させました。

volatile struct {
int (*printf)(const char *, ...);
} debug;


debug.printf = USARTPrintf;

debug.printf("\r\nTime:%s", __TIME__); // なんかかっこいいかも!

ということで自己満足だけどやっとスッキリしたUSART版printfが完成したのでありましたー(^ω^)
前回の「QuickTimeフォーマットの勉強 その1」の知識量だけではQuickTimeフォーマットの全体像を知るには無理があったようで、もう少し突き詰めないと満足に再生できないことが分かったので「QuickTimeフォーマットの勉強 その2」をまとめました。

$とんすけぶろぐ
↑ムービーインスペクタ(サウンドやビデオの詳細情報)

$とんすけぶろぐ
↑シークバーを目一杯右端に持ってきたときのフレーム番号(全フレーム数)

ムービーファイルの再生時間を取得する
Media Header Atom(mdhd)にタイムスケールとデュレーション情報が記述されているのでここから取り出します。

タイムスケールとは1秒間をいくらに分けるか決める時間尺度です。
デュレーションとは長さのことです。

再生時間はデュレーション÷タイムスケールで求めることができます。

$とんすけぶろぐ
↑Media Header Atomの構造

$とんすけぶろぐ
↑サウンドトラックのmdhdから取り出すと、
タイムスケール:0xAC44(44100)
デュレーション:0x3CF84E7(63931623)
ここから再生時間は63931623/44100≒1449.697sなので24分9.69秒が求まります。

$とんすけぶろぐ
↑同様にビデオトラックのmdhdから取り出すと、
タイムスケール:0x258(600)
デュレーション:0xD45BA(869818)
ここから再生時間は869818/600≒1449.697sなので24分9.69秒となりサウンドトラックの再生時間と一致しました。

記事編集中
STM32F2でMotion JPEGの再生に挑戦してます。
動画ファイルのコンテナにはAVIやQuickTimeなどいろいろがありますが、音楽プレーヤを作ったときにMP4のIDタグを取り出した経験があったので馴染みのあるQuickTimeでデコードして構造を勉強してます。

QuickTime File Format Specification
http://developer.apple.com/library/mac/documentation/QuickTime/QTFF/qtff.pdf

↑QuickTimeフォーマットの仕様書

QuickTimeはAtomという階層型の入れ子で構成されていて、再生情報やデータ(ビデオやサウンドやテキスト等)は全てAtomに入れられ管理されています。
各Atomは自身の大きさとタイプ(ASCII文字列)が先頭に記述されていて、子を持つか、どういった情報を持つかなど予め仕様書で定義されています。

動画ファイルの全Atomを取り出してみました。画像の左文字列がAtomの種類で右がその大きさです。
親子の関係を表記しておらずただ単に列挙しただけのものです。
とんすけぶろぐ
選択表示しているtrakがそれぞれサウンドトラックとビデオトラックです。
stxxというAtomがサンプルテーブルになっており、各サンプルの表示デュレーションやチャンクのまとめ方、各サンプルのファイルオフセットの位置等が記述されています。

ビデオトラックのstcoから1枚目のJPEG画像が格納されてあるファイルオフセットの位置を探ってみました。
選択部分の後ろ4バイトの0x000158B8が該当するのでそこに飛んでみます。
$とんすけぶろぐ

するとJPEGのStart of Imageマーカー(FFD8)がちゃんと現れました。
とんすけぶろぐ

JPEG画像の終端が分からないといけないので調べてみるとサイズはstszに記述されていました。
1枚目の画像は選択範囲の後ろ4バイトの0x00000A45です。
とんすけぶろぐ

さっきの先頭オフセットから0xA45分だけ選択してみると終端にJPEGのEnd of Imageマーカー(FFD9)が現れました。その直後にまたSOIマーカーがきてます。
$とんすけぶろぐ

これでQuickTimeのMOVファイルからMotion JPEGの1フレーム画像の位置と大きさを求めることができました。
これを取り込んでlibjpegでデコードして描画を繰り返せばとりあえず動画再生できるかも。
表示デュレーションや音楽との再生をとりあえず後回し^^

しかしここでちょっとした問題が><;
上の検証に使った動画はQVGAサイズ24分程度のもので約700MBの容量があります。
ビデオトラック情報が書かれてあるtrakのAtomはファイル先頭より692,413,886バイト後方に位置しています。
そこへ飛ぶために自作のfseek関数でシークすると9秒もかかってしまいました><;
クラスタサイズは32KBなので約2万個以上ものアロケーションテーブルを辿ったことになります。
改良次第でもうちょっと高速化することができるかなぁ。
ネタとモチベーション枯渇中・・・。

USBとEthernetをごにょごにょしたいけど別途PHYが必要なのでちょっと足踏み中。
最大の興味はSTM32F2のOn-The-Go(USBホストにもデバイスにもなれるというデュアルロール機能)


ソフトウェア的なモノであればなにか移植して遊べないかなぁ。
うーむ・・・。

画像ないと映えないのでとりあえず今使ってる壁紙でも(^^;A
$とんすけぶろぐ
ネタがないので過去に録ってたハートキャッチプリキュアのピアノソロでも(^_^;A


毎週見てたわけじゃないけどこの曲がなぜか琴線に触れてフルで暗譜できるまで弾くようになったw
相変わらずミスってる大事なとこミスってる><;