12

私はXuggler(内部で使用していると思いますffmpeg使用して次のことを実行しようとしています。

  • (小型のTTLシリアルカメラからの)生のMPJPEGビデオビットストリームを受け入れ、それをh.264にエンコード/トランスコードします。と
  • (マイクからの)生のオーディオビットストリームを受け入れ、それをAACにエンコードします。それから
  • 2つの(オーディオとビデオ)ビットストリームを一緒にMPEG-TSコンテナにマルチプレクサします

私は彼らの優れたチュートリアルのいくつかを見たり読んだりしました、そしてこれまでのところ私が持っているものはここにあります:

// I'll worry about implementing this functionality later, but
// involves querying native device drivers.
byte[] nextMjpeg = getNextMjpegFromSerialPort();

// I'll also worry about implementing this functionality as well;
// I'm simply providing these for thoroughness.
BufferedImage mjpeg = MjpegFactory.newMjpeg(nextMjpeg);

// Specify a h.264 video stream (how?)
String h264Stream = "???";

IMediaWriter writer = ToolFactory.makeWriter(h264Stream);
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264);
writer.encodeVideo(0, mjpeg);

一つには、私はここに近いと思いますが、それでも正しくありません。そして、私はビデオコードの例を読んだだけでここまで到達しました(オーディオではありません-良いオーディオの例は見つかりません)。

文字通り、Xugglerの実装に含まれる生のビデオおよびオーディオフィードへのバイトレベルのアクセスを取得します。しかし、私の人生では、それらをh.264 / AAC/MPEG-TS形式にする方法がわかりません。ここで助けてくれてありがとう。

4

2 に答える 2

16

Xugglerのこのサンプルコードを見ると、ビデオをH.264としてエンコードし、MPEG2TSコンテナに多重化するために次のように機能するはずです。

IMediaWriter writer = ToolFactory.makeWriter("output.ts");
writer.addVideoStream(0, 0, ICodec.ID.CODEC_ID_H264, width, height);
for (...)
{

   BufferedImage mjpeg = ...;

   writer.encodeVideo(0, mjpeg);
}

コンテナタイプはファイル拡張子から推測され、コーデックは明示的に指定されます。

オーディオとビデオを多重化するには、次のようにします。

writer.addVideoStream(videoStreamIndex, 0, videoCodec, width, height);
writer.addAudioStream(audioStreamIndex, 0, audioCodec, channelCount, sampleRate);

while (... have more data ...)
{
    BufferedImage videoFrame = ...;
    long videoFrameTime = ...; // this is the time to display this frame
    writer.encodeVideo(videoStreamIndex, videoFrame, videoFrameTime, DEFAULT_TIME_UNIT);

    short[] audioSamples = ...; // the size of this array should be number of samples * channelCount
    long audioSamplesTime = ...; // this is the time to play back this bit of audio
    writer.encodeAudio(audioStreamIndex, audioSamples, audioSamplesTime, DEFAULT_TIME_UNIT);
}

この場合、コードがオーディオとビデオのインターリーブを担当していると思います。ループを通過するたびに、使用可能なデータ(オーディオサンプルのチャンクまたはビデオフレーム)に基づいて、 encodeAudio()またはencodeVideo()のいずれかを呼び出します。 )タイムスタンプが早い

IStreamCoderに基づいて、最終的に使用する可能性のある別の低レベルAPIがあります。これにより、さまざまなパラメーターをより詳細に制御できます。私はあなたがそれを使う必要はないと思います。

あなたが尋ねた特定の質問に答えるために:

(1)「BufferedImage(M / JPEG)をh.264ストリームにエンコードする」-すでに理解しているwriter.addVideoStream(..., ICodec.ID.CODEC_ID_H264)ので、H.264コーデックを取得していることを確認してください。トランスポートストリーム(MPEG2 TS)コンテナmakeWriter()を取得するには、拡張子が.tsのファイル名で呼び出すだけです。

(2)「生のオーディオフィードの「BufferedImage相当」が何であるかを理解する」-これはshort []またはIAudioSamplesオブジェクトのいずれかです(どちらも機能しているようですが、IAudioSamplesは多くのIBufferから構築する必要がありますそれほど単純ではありません)。

(3)「このオーディオクラスをAACオーディオストリームにエンコードする」-callwriter.addAudioStream(..., ICodec.ID.CODEC_ID_AAC, channelCount, sampleRate)

(4)「両方のストリームを同じMPEG-TSコンテナに多重化する」-makeWriter()コンテナタイプを設定する.tsファイル名で呼び出します。オーディオ/ビデオを正しく同期するには、encodeVideo()/ encodeAudio()を正しい順序で呼び出す必要があります。

PS常に利用可能な最も早いオーディオ/ビデオを最初に渡します。たとえば、440サンプルの長さ(44000 Hzのサンプルレート、440/44000 = 0.01秒)のオーディオチャンクと、正確に25 fps(1/25 = 0.04秒)のビデオがある場合、それらをライターに渡します。この注文:

video0 @ 0.00 sec
audio0 @ 0.00 sec
audio1 @ 0.01 sec
audio2 @ 0.02 sec
audio3 @ 0.03 sec
video1 @ 0.04 sec
audio4 @ 0.04 sec
audio5 @ 0.05 sec

...など

連続するオーディオ/ビデオのタイムスタンプが比較的近い限り、ほとんどの再生デバイスはおそらくストリームに問題はありませんが、これは完璧なマルチプレクサに対して行うことです。

PS参照したいドキュメントがいくつかあります:Xugglerクラス図ToolFactoryIMediaWriterICodec

于 2012-12-18T14:09:10.860 に答える
0

gstreamerを見る必要があると思います:http://gstreamer.freedesktop.org/カメラ入力をキャプチャしてlibx264およびaacプラグインにパイプし、それらをmpegtsマルチプレクサに渡すことができるプラグインを探す必要があります。

gstreamerのパイプラインは次のようになります。

v4l2src queue-size=15 ! video/x-raw,framerate=25/1,width=384,height=576 ! \
  avenc_mpeg4 name=venc \
alsasrc ! audio/x-raw,rate=48000,channels=1 ! audioconvert ! lamemp3enc name=aenc \
avimux name=mux ! filesink location=rec.avi venc. ! mux. aenc. ! mux.

このパイプラインでは、mpeg4およびmp3エンコーダーが使用されており、ストリームはaviに多重化されています。libx264とaacのプラグインを見つけることができるはずです。さらにポインタが必要な場合はお知らせください。

于 2012-12-15T14:45:26.417 に答える