Armadilloフォーラム

Gstreamerで動画を再生中に縮小及び復帰する方法について

alphatc

2016年11月29日 14時45分

お世話になっております。alphatcと申します。
Armadillo-840にてクロス環境のc言語でGstreamerを利用しております。

目的はHDMI出力(FB0)へFHD動画を再生中に描画サイズを徐々に縮小及び復帰することです。

例えばstride=1920,x-offset=0,y-offset=0,width=1920,height=1080で再生している最中に
stride=1920,x-offset=0,y-offset=0,width=640,height=360の大きさに徐々に小さくして
元のサイズに徐々に戻すことを想定しています。
また、フレームレートはなるべく落ちない方法を模索しております。

現状はc言語にて再生開始時に設定した任意のサイズ(及び任意位置)を再生するまではできておりますが、
再生中に拡大縮小を行う方法が見当たっておりません。

そこで、
①そもそもArmadillo-840のカーネル、AVコーデックミドルウェアが対応されているのかどうか
②実現可能であればどのような方法でしょうか
③フレームレートが落ちないベストな方法は何でしょうか
教えて頂きたいです。

よろしくお願いします。

コメント

at_yashi

2016年11月30日 16時45分

試しにやってみたらできました。
でも、a)ドライバーには修正が必要なのと、b) 縮小したときに描画されない場所を消すという作業が必要になりそうです。

a) の方、公開できる形にしてみますので少々お待ち下さい。
b) の方は、....お願いします。

フレーム毎にサイズを変更すると、スムーズに拡縮されるように見えます。ただ、v4l2にはそのようなインターフェイスがありません。既存のインターフェイスを使うならVIDIOC_S_FMTによる設定になりますが、これは enqueue したバッファーと同期しないので、縮小させるバッファーの指定が難しいです。用途によっては拡張インターフェイスを作成する方が良いかもしれません。

もし良ければ、どういう使い方を想定しているか、教えていただけますか?

at_yashi

2016年11月30日 17時36分

自動で動画を拡縮するようにドライバーを修正してみました。

アプリケーションからコントロールするには、v4l2のインターフェイスを作成する必要があります。
とりあえず ファームウェアのデモということで。

ファイル ファイルの説明
0001-acm-Supports-resizing-during-decoding.patch
0002-acm-Demo-patch-for-full-HD-monitor.patch

alphatc

2016年12月1日 12時11分

早速のご教授ありがとうございます。

まず、整理させて頂きたいのですが、
有効な方法の一つとして、「AVコーデックミドルウェアのドライバーを変更すること」という認識でよろしいでしょうか。

b)の描画されない部分を消すというのは
例えば縮小の描画前に背景色(黒)で先に全体を塗りつぶすようなことでよいのでしょうか、
それとも描画されない場所だけを後から塗りつぶすようなイメージでしょうか。

使い方としましては、アプリケーションからコントロールすることを想定しています。
再生中に任意のタイミングで縮小、また任意のタイミングで復帰するような使い方です。
静的パラメータとしては縮小位置xy、縮小サイズwh、遷移フレーム数で
再生開始時に静的パラメータを渡しておいて、動的に縮小と復帰のトリガーが渡すという感じです。

at_yashi

2016年12月1日 13時03分

> 有効な方法の一つとして、「AVコーデックミドルウェアのドライバーを変更すること」という認識でよろしいでしょうか。

「各フレームのデコード後のサイズ変更に、firmwareは対応しているが、現在のドライバーはしていない」
ということです。

> b)の描画されない部分を消すというのは
> 例えば縮小の描画前に背景色(黒)で先に全体を塗りつぶすようなことでよいのでしょうか、
> それとも描画されない場所だけを後から塗りつぶすようなイメージでしょうか。

どちらでも構いません。縮小するサイズによって、どちらの方が早いか決まりそうです。
アプリケーションでも、ドライバー内でも実施可能だと思います。

> 使い方としましては、アプリケーションからコントロールすることを想定しています。
> 再生中に任意のタイミングで縮小、また任意のタイミングで復帰するような使い方です。
> 静的パラメータとしては縮小位置xy、縮小サイズwh、遷移フレーム数で
> 再生開始時に静的パラメータを渡しておいて、動的に縮小と復帰のトリガーが渡すという感じです。

なるほど。ドライバーに新しく専用のインターフェイスを追加する形で対応できそうですね。

> 既存のインターフェイスを使うならVIDIOC_S_FMTによる設定になりますが

これ間違っていました。VIDIOC_S_FMT は、デコード後の大きさではなく
バッファーの大きさを決めるので、他のインターフェイスを使わないとだめですね。

alphatc

2016年12月2日 18時12分

ありがとうございます。まだまだ初心者なものですみません。またご教授願います。

> > b)の描画されない部分を消すというのは
> > 例えば縮小の描画前に背景色(黒)で先に全体を塗りつぶすようなことでよいのでしょうか、
> > それとも描画されない場所だけを後から塗りつぶすようなイメージでしょうか。
>
> どちらでも構いません。縮小するサイズによって、どちらの方が早いか決まりそうです。
> アプリケーションでも、ドライバー内でも実施可能だと思います。

ドライバー内で黒の全消ししておきたいと考えております。具体的にどのように記述すればよいのでしょうか。

> > 使い方としましては、アプリケーションからコントロールすることを想定しています。
> > 再生中に任意のタイミングで縮小、また任意のタイミングで復帰するような使い方です。
> > 静的パラメータとしては縮小位置xy、縮小サイズwh、遷移フレーム数で
> > 再生開始時に静的パラメータを渡しておいて、動的に縮小と復帰のトリガーが渡すという感じです。
>
> なるほど。ドライバーに新しく専用のインターフェイスを追加する形で対応できそうですね。

静的なパラメータはacmh264decのプロパティを追加するようなことでしょうか。
動的なトリガーは新規の関数を追加しておき、コールするようなことでしょうか。
こちらも具体的に教えてください。お手数かけますが、よろしくお願いします。

at_yashi

2016年12月8日 11時37分

> ドライバー内で黒の全消ししておきたいと考えております。具体的にどのように記述すればよいのでしょうか。

linux-3.4-at/drivers/media/video/acm/ 以下に ACM 関連のドライバーが入っています。acm_h264dec.cacm_h264dec_m2m_async_decode_work_func() の中で rto_h264dec_decode() を呼び出してデコードしています。

この関数の、dst_phys_addr が書き出し先のバッファーのアドレスなので、これを memset() すれば動くんじゃないかと思います。

> 静的なパラメータはacmh264decのプロパティを追加するようなことでしょうか。
> 動的なトリガーは新規の関数を追加しておき、コールするようなことでしょうか。
> こちらも具体的に教えてください。お手数かけますが、よろしくお願いします。

どちらも v4l2 の ioctl() になるはずです。パラーメーターをセットする ioctl と、トリガー用の ioctl。

ioctl を追加するには V4L2 の v4l2_ext_controls を使う方法は、どうですか?

https://www.linuxtv.org/downloads/legacy/video4linux/API/V4L2_API/spec-…

acm_h264dec.cacm_h264dec_ioctl_ops に追加します。

alphatc

2016年12月9日 10時24分

情報連携ありがとうございます。

memset() については承知しました。

ioctl()についてですが、
acm_h264dec.cacm_h264dec_ioctl_ops に新規でパラメータを追加すれば良いのでしょうか。

また、パラメータをセットする方法としては、以下のどのパターンでしょうか。
・gstreamerのgst_caps_new_simple()によるフィルターケイパビリティへのセット
・gstreamerのg_object_get()によるエレメントのプロパティへのセット
・直接ドライバのパラメータへのセット ioctl()?
・その他

お手数おかけしますが、具体的にご教授頂きたく、お願い致します。

at_yashi

2016年12月9日 10時51分

まずはドライバーで実装する必要があるので acm_h264dec_ioctl_ops

    .vidioc_s_ext_ctrls              = my_set_ext_ctrl_func,

と、VIDIOC_S_EXT_CTRLS に反応する関数を追加実装するという意味です。my_set_ext_ctrl_func() では、パラメーターを受けつけるコマンド ID とトリガーとして動くコマンド ID の2つに対応できるように作成します。 acm_h264dec_video_dev_vidioc_s_ctrl()が参考になると思います。ioctlの一般的な話については、 https://static.lwn.net/images/pdf/LDD3/ch06.pdf などが良いと思います。

(もし自分しか使わないのであれば acm_h264dec_video_dev_vidioc_s_ctrl() を拡張してしまっても良いです。そもそもこのドライバーは VIDIOC_S_CTRL で標準ではない ID を受けちゃっているので....)

その後、この ioctl を GStreamer から呼びだすように作る必要があります。

分りづらくてすみません。

alphatc

2016年12月9日 13時27分

今回は手数を少なくしたいので、
acm_h264dec_video_dev_vidioc_s_ctrl() を拡張するパターンで行きたいと思います。

追加したいパラメータは
struct acm_h264dec_m2m_async_ctx_priv のメンバーに追加するような感じでしょうか。

> その後、この ioctl を GStreamer から呼びだすように作る必要があります。

この部分を具体的に教えてください。
また、GStreamer側のソースにも変更を加える必要があるのでしょうか。

お手数かけますがよろしくお願いします。