欢迎关注公众号:冒泡的肥皂
1.效果图延时超过了10s
2.拉流
-
首先要回个头消息
-
需要首先发送"AVC sequence header(AVCDecoderConfigurationRecord)"和"AAC sequence header(aacAudioSpecificConfig)",这两项数据包含的是重要的编码信息,没有它们,解码器将无法解码。
//Video的编码格式AVC也就是常说的H264
public boolean isH264KeyFrame() {
return videoData.length > 1 && videoData[0] == 0x17;
}
//说明后面承载的数据是H264的序列头也就是编码器配置SPS PPS而不是裸数据Nalu
public boolean isAVCDecoderConfigurationRecord() {
return isH264KeyFrame() && videoData.length > 2 && videoData[1] == 0x00;
}
public boolean isAACAudioSpecificConfig(){
return audioData.length>1 && audioData[1]==0;
}
if(msg instanceof VideoMessage) {
VideoMessage vm=(VideoMessage)msg
//设置avc信息
if (vm.isAVCDecoderConfigurationRecord()) {
log.info("avcDecoderConfigurationRecord ok");
avcDecoderConfigurationRecord = vm;
}
}
if(msg instanceof AudioMessage) {
AudioMessage am=(AudioMessage) msg;
//acc
if (am.isAACAudioSpecificConfig()) {
aacAudioSpecificConfig = am;
}
}
- 内容
encodeMediaAsFlvTagAndPrevTagSize
public synchronized void addHttpFlvSubscriber(Channel channel) {
httpFLvSubscribers.add(channel);
log.info("http flv subscriber : {} is added to stream :{}", channel, streamName);
// 1.flv媒体信息描述
byte[] meta = encodeFlvHeaderAndMetadata();
channel.writeAndFlush(Unpooled.wrappedBuffer(meta));
// 2. avcDecoderConfigurationRecord
avcDecoderConfigurationRecord.setTimestamp(content.get(0).getTimestamp());
byte[] config = encodeMediaAsFlvTagAndPrevTagSize(avcDecoderConfigurationRecord);
channel.writeAndFlush(Unpooled.wrappedBuffer(config));
// 3. write aacAudioSpecificConfig
if (aacAudioSpecificConfig != null) {
aacAudioSpecificConfig.setTimestamp(content.get(0).getTimestamp());
byte[] aac = encodeMediaAsFlvTagAndPrevTagSize(aacAudioSpecificConfig);
channel.writeAndFlush(Unpooled.wrappedBuffer(aac));
}
// 4. write content 数据转发
for (RtmpMediaMessage msg : content) {
channel.writeAndFlush(Unpooled.wrappedBuffer(encodeMediaAsFlvTagAndPrevTagSize(msg)));
}
}