Xuggler编码和复用

我正在尝试使用Xuggler (我相信在引擎盖下使用ffmpeg )来执行以下操作:

  • 接受原始MPJPEGvideo比特流(来自小型TTL串行摄像机)并将其编码/转码为h.264; 和
  • 接受原始音频bitsream(来自麦克风)并将其编码为AAC; 然后
  • 将两个(音频和video)比特组合在一起成为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); 

首先,我想我离这里很近,但它仍然不正确; 我只是通过阅读video代码示例(而不是音频 – 我找不到任何好的音频示例)来实现这一目标。

从字面上看,我将获得对Xuggler实现中的原始video和音频源的字节级访问。 但对于我的生活,我无法弄清楚如何将它们变成h.264 / AAC / MPEG-TS格式。 在此提前感谢您的帮助。

看看Xuggler这个示例代码 ,以下应该可以将video编码为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); } 

从文件扩展名中猜出容器类型,显式指定编解码器。

要复用音频和video,您可以执行以下操作:

 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); } 

在这种情况下,我相信您的代码负责交错音频和video:您希望在每次通过循环时调用encodeAudio() encodeVideo(),具体取决于可用的数据(一大块音频样本或video帧) )有一个较早的时间戳

基于IStreamCoder ,您可能最终会使用另一个较低级别的API,它可以更好地控制各种参数。 我认为你不需要使用它。

要回答您提出的具体问题:

(1)“将BufferedImage(M / JPEG)编码为h.264流” – 您已经想到了, writer.addVideoStream(..., ICodec.ID.CODEC_ID_H264)确保您获得H.264 编解码器 。 要获取传输流(MPEG2 TS) 容器 ,只需使用扩展名为.ts的文件名调用makeWriter()

(2)“弄清楚原始音频输入的”BufferedImage等效“是什么” – 这是一个短[]或IAudioSamples对象(两者似乎都有效,但是IAudioSamples必须是从一个IBuffer构建的不太直白)。

(3)“将此音频类编码为AAC音频流” – 调用writer.addAudioStream(..., ICodec.ID.CODEC_ID_AAC, channelCount, sampleRate)

(4)“将两个流复用到同一个MPEG-TS容器中” – 使用.ts文件名调用makeWriter() ,该文件名设置容器类型。 要获得正确的音频/video同步,您可能需要以正确的顺序调用encodeVideo()/ encodeAudio()。

PS始终首先传递最早的音频/video。 例如,如果您的音频块长度为440个样本(采样率为44000 Hz,440/44000 = 0.01秒),video速度恰好为25fps(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 

……等等

只要连续的音频/video时间戳相对接近,大多数播放设备都可以使用流,但这就是你为完美的多路复用器所做的。

PS你可能想要参考一些文档: Xuggler类图 , ToolFactory , IMediaWriter , ICodec 。

我想你应该看看gstreamer: http : //gstreamer.freedesktop.org/你必须寻找可以捕获摄像头输入的插件,然后将它传输到libx264和aac插件,然后通过mpegts muxer传递它们。

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的插件。 如果您需要进一步的指示,请告诉我。