Broadcom Nexus学习 (四) Video Decoder


此图显示了以有线电视为源,如何一步步通过各个 Interface接到输出去的。

 

InputBand是有线电视输入源,ParserBand则是解析器。 PidChannel分为Video和Audio。分别将Video和Audio数据传输向Video DecoderAudioDecoder。之后,Audio如上一章所讲进入Mixer到DAC。

而Video则通过VideoDecoder解压后显示于DisplayVideoWindow上。

 

代码流程如下:

1. NEXUS_Platform_GetStreamerInputBand(0, &inputBand);

从Platform处得到Streamer InputBand,Platform将参数1(index)0 设置为Tune Stream。

所以参数2(inputBand)返回的是一个InputBand。 它就是Tune Stream。 即位Tune 传入的有线电视信号。

 

2. 设置Parser: 

parserBand = NEXUS_ParserBand_e0;
NEXUS_ParserBand_GetSettings(parserBand, &parserBandSettings);
parserBandSettings.sourceType = NEXUS_ParserBandSourceType_eInputBand;
parserBandSettings.sourceTypeSettings.inputBand = inputBand;
parserBandSettings.transportType = NEXUS_TransportType_eTs;
NEXUS_ParserBand_SetSettings(parserBand, &parserBandSettings);

 

3. videoPidChannel = NEXUS_PidChannel_Open(parserBand, 0x11, NULL);

打开Pid Channel from parser band.

前面有了ParserBand,并指定了ParserBand的InputBand。这里则打开PidChannel,输入为此ParserBand。

但Sam不明白此处参数2的PID为什么是0x11。(Sam之后发现这个值与音视频流有关,见后面的讲解。)

 

 

4. 设置VideoDecoder:

NEXUS_VideoDecoder_GetDefaultStartSettings(&videoProgram);
videoProgram.codec = NEXUS_VideoCodec_eMpeg2;
videoProgram.pidChannel = videoPidChannel;

 

5. 创建Display并于Platform Output 连接:

NEXUS_Display_GetDefaultSettings(&displaySettings);
 displaySettings.format = NEXUS_VideoFormat_eNtsc;
 display = NEXUS_Display_Open(0, &displaySettings);
 NEXUS_Display_AddOutput(display, NEXUS_ComponentOutput_GetConnector(platformConfig.outputs.component[0]));
 NEXUS_Display_AddOutput(display, NEXUS_CompositeOutput_GetConnector(platformConfig.outputs.composite[0]));
 if (platformConfig.outputs.svideo[0]) {
     NEXUS_Display_AddOutput(display, NEXUS_SvideoOutput_GetConnector(platformConfig.outputs.svideo[0]));
 }

 

6. 创建VideoWindow:

window = NEXUS_VideoWindow_Open(display, 0);

Open a VideoWindow from its Display.

 

7. 打开VideoDecoder,并将其连接到Video Windows。

vdecode = NEXUS_VideoDecoder_Open(0, NULL);
NEXUS_VideoWindow_AddInput(window, NEXUS_VideoDecoder_GetConnector(vdecode));

 

8. 开始Decoder:

NEXUS_VideoDecoder_Start(vdecode, &videoProgram);

 

 

9. 关闭:

NEXUS_VideoDecoder_Stop(vdecode);
 NEXUS_VideoWindow_RemoveAllInputs(window);
 NEXUS_VideoInput_Shutdown(NEXUS_VideoDecoder_GetConnector(vdecode));
 NEXUS_VideoWindow_Close(window);
 NEXUS_Display_Close(display);
 NEXUS_VideoDecoder_Close(vdecode);
 NEXUS_PidChannel_Close(videoPidChannel);

 

 

 具体过程很简单:

 1.得到Index为0的StreamerInputBand。即是Tune的输入。

 2.设置ParserBand。将inputBand设置为ParserBand的Input。

 3.打开Video And Audio Pid Channel. NEXUS_PidChannel_Open();

   Open a new PID channel from a parser band.

   其中参数2:PID:PID (packet ID) that will be selected from the parser band. If TS, this is a PID. If PES, this is a PES stream id.

   这个PID的数值,与具体音频视频格式有关。例如,TS流,PS流中各不相同。

   有个软件叫做:MediaInfo:它可以查看指定音视频文件的Video,Audio ID。

 

 4. 设置VideoDecoder AudioDecoder的StartSetting。 

    主要设置codec(视频音频格式)和pidChannel(先前建立的Pid Channel)。

 

 5. 打开AudioDecoder,并将其连接到AudioDAC上。

 6. 设置,建立Display.并将Display连接到Display Output(分量,HDMI,混合,S-Video)

 7. Open a VideoWindow from its Display. index=0.(NEXUS_VideoWindow_Open)

 8. Open a new VideoDecoder.. (NEXUS_VideoDecoder_Open). 并将VideoDecoder加入为VideoWindow的Input。(NEXUS_VideoWindow_AddInput)

 9. 开始播放:NEXUS_VideoDecoder_Start,NEXUS_AudioDecoder_Start。

 

 

 

 

 到这里,从Tune中输入出Video,Audio已经完成了。但大家会想,是否可以像之前播放本地Audio那样播放本地的Video File呢?当然是可以的,PlayPump就是做这事的。(Audio Decoder中有对应音频的例子 http://blog.sina.com.cn/s/blog_602f87700100nwlq.html

 

思路与之前Audio Decoder类似:

打开,PlayPump, Playback,将PlayPump设置为数据源,利用Playback打开PidChannel。并将PidChannel与VideoDecoder, AudioDecoder联系起来。再将VideoDecoder连到Display的VideoWindow上,通过Display的Output显示在TV上。 AudioDecoder连到Mixer, Mixer中与AudioPlayback混和后进入AudioDAC。

 

先看图示:


下面看具体步骤:

 

1. 创建PlayPump, Playback:

playpump = NEXUS_Playpump_Open(0, NULL);

playback = NEXUS_Playback_Create();


讲解:

NEXUS_PlaypumpHandle NEXUS_Playpump_Open(
                unsigned indexconst NEXUS_PlaypumpOpenSettings *pSettings )

打开一个Playpump Interface。

Open a new Playpump interface.

Broadcom7413支持5个Playpump。 所以Index不能超过4。

 

NEXUS_PlaybackHandle NEXUS_Playback_Create(void)

创建一个Playback实例。Create a new playback instance.

我们创建这个Playback,用来打开PID Channel。

 

2. 使用Nexus接口打开视频文件:

file = NEXUS_FilePlay_OpenPosix(fname, NULL);

此FilePlayHandle用来传递给Playback供输入数据源。

 

3. 设置Playback:

这里主要是设置PlayPump为Playback的playpump. 并设置Playpump的数据传输格式。

NEXUS_Playback_GetSettings(playback, &playbackSettings);
playbackSettings.playpump = playpump;  //此处设置playback 的playpump, 用来给Decoder填充数据。

//数据传输格式,包括:MPEG1,DVD VOB,MPEG2-TS(基于传输的),MPEG2-PS(基于存储的)

playbackSettings.playpumpSettings.transportType = NEXUS_TransportType_eTs;

NEXUS_Playback_SetSettings(playback, &playbackSettings);

 

Sam在使用MediaInfo软件查看目标视频时发现,它是MPEG2-PS。所以修改如下:

playbackSettings.playpumpSettings.transportType = NEXUS_TransportType_eMpeg2Pes;

 

 

4. 创建AudioDecoder,并将其连接到DAC:

audioDecoder = NEXUS_AudioDecoder_Open(0, NULL);
NEXUS_AudioOutput_AddInput(
        NEXUS_AudioDac_GetConnector(platformConfig.outputs.audioDacs[0]),
        NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));

其实此处AudioDecoder也可以连接到Mixer中。

 

5. 打开Display并指定其Output:

display = NEXUS_Display_Open(0, NULL);

NEXUS_Display_AddOutput(display, NEXUS_ComponentOutput_GetConnector(platformConfig.outputs.component[0]));

 

 

6. 创建VideoWindow, VideoDecoder,并将VideoDecoder设置为VideoWindow的Input:

window = NEXUS_VideoWindow_Open(display, 0);
videoDecoder = NEXUS_VideoDecoder_Open(0, NULL);
NEXUS_VideoWindow_AddInput(window, NEXUS_VideoDecoder_GetConnector(videoDecoder));


 

7. 利用Playback,打开Video PidChannel, Audio PidChannel:

NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);

playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eVideo;
playbackPidSettings.pidTypeSettings.video.codec = NEXUS_VideoCodec_eMpeg2;    playbackPidSettings.pidTypeSettings.video.index = true;
playbackPidSettings.pidTypeSettings.video.decoder = videoDecoder;

videoPidChannel = NEXUS_Playback_OpenPidChannel(playback, 0x21, &playbackPidSettings);

 

NEXUS_Playback_GetDefaultPidChannelSettings(&playbackPidSettings);
playbackPidSettings.pidSettings.pidType = NEXUS_PidType_eAudio;
playbackPidSettings.pidSettings.pidTypeSettings.audio.codec = NEXUS_AudioCodec_eMpeg;

playbackPidSettings.pidTypeSettings.audio.primary = audioDecoder;
audioPidChannel = NEXUS_Playback_OpenPidChannel(playback, 0x22, &playbackPidSettings);

 

首先得到Playback的Default PidChannel的设置,

1.分别指定其PlayPump的Type为Video和Audio。

2.分别指定PlayPump的Codec格式为:NEXUS_VideoCodec_eMpeg2,NEXUS_AudioCodec_eMpeg。 即为:MPEG2-Vidoe和MPEG1/2 -layer 1/2.

3.分别指出PID Channel的Video和Audio的解码器。注意,他们指定的Struct其实并不对应。

4。利用PlayBack打开PidChannel:

注意:PID分别为0x21,0x22. 此处PID与具体媒体格式对应。可以使用MedioInfo查看。

Sam查到自己的视频文件为:0xE0,0xC0.

 

 

8. 设置VideoDecoder和AudioDecoder的StrartSetting,并指定各自的PIDChannel:

    NEXUS_VideoDecoder_GetDefaultStartSettings(&videoProgram);
    videoProgram.codec = NEXUS_VideoCodec_eMpeg2;
    videoProgram.pidChannel = videoPidChannel;

    NEXUS_AudioDecoder_GetDefaultStartSettings(&audioProgram);
    audioProgram.codec = NEXUS_AudioCodec_eMpeg;
    audioProgram.pidChannel = audioPidChannel;

 

指定VideoDecoder Codec和AudioDecoder Codec的格式。即解码器的格式。并指定各自的PIDChannel。

之前PIDChannel得到了VideoDecoder和AudioDecoder。

现在AudioDecoder,VideoDecoder得到对应PIDChannel。有点相互确认的意思。呵呵。

 

 

9. 正式开始解码和播放:

    NEXUS_VideoDecoder_Start(videoDecoder, &videoProgram);
    NEXUS_AudioDecoder_Start(audioDecoder, &audioProgram);
    NEXUS_Playback_Start(playback, file, NULL);

 

 

如果不处理,会循环播放。可以利用playbackSettings.endOfStreamCallback.callback察看是否播放完毕。完毕则退出。

 

 

10。退出:

NEXUS_VideoDecoder_Stop(videoDecoder);
    NEXUS_AudioDecoder_Stop(audioDecoder);
    NEXUS_Playback_Stop(playback);
    NEXUS_FilePlay_Close(file);
    NEXUS_Playback_Destroy(playback);
    NEXUS_Playpump_Close(playpump);
    NEXUS_VideoInput_Shutdown(NEXUS_VideoDecoder_GetConnector(videoDecoder));
    NEXUS_VideoDecoder_Close(videoDecoder);
   NEXUS_AudioOutput_RemoveAllInputs(NEXUS_AudioDac_GetConnector(platformConfig.outputs.audioDacs[0]));
   NEXUS_AudioOutput_RemoveAllInputs(NEXUS_SpdifOutput_GetConnector(platformConfig.outputs.spdif[0]));
    NEXUS_AudioInput_Shutdown(NEXUS_AudioDecoder_GetConnector(audioDecoder, NEXUS_AudioDecoderConnectorType_eStereo));
    NEXUS_AudioDecoder_Close(audioDecoder);
    NEXUS_Display_Close(display);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值