播放HLS时,部分TS分片的sps排列是:
0 0 0 1 9 240 0 0 0 1 103 。。。 0 0 0 1 104。。。
其对应的内容是:
这里针对这种情况做了处理,提取出其中的sps数据给到MediaCodec,避免MediaCodec初始化失败。
需要这种视频链接的,我可以发出来,不过视频链接只有24小时有效。
issues如下:
ijkmedia/ijkplayer/android/pipeline/ffpipenode_android_mediacodec_vdec.c
@@ -245,24 +245,23 @@ static int recreate_format_l(JNIEnv *env, IJKFF_Pipenode *node)
SDL_AMediaFormat_setBuffer(opaque->input_aformat, "csd-0", convert_buffer, esds_size);
free(convert_buffer);
} else {
//先只考虑h264的情况,H265这种情况我也没见过
if(opaque->avctx->codec_id == AV_CODEC_ID_H264 && opaque->avctx->extradata_size > 6){
//参考 https://blog.csdn.net/chinabinlang/article/details/78181110
//参考 https://blog.csdn.net/dxpqxb/article/details/7631644
//这种视频是:AUD+SPS+PPS的情况
if(opaque->codecpar->codec_id == AV_CODEC_ID_H264 && opaque->codecpar->extradata_size > 6){
// https://blog.csdn.net/chinabinlang/article/details/78181110
// https://blog.csdn.net/dxpqxb/article/details/7631644
// AUD+SPS+PPS的情况
// 103 代表sps
// 104 代表pps
int spsIndex = -1;
int ppsIndex = -1;
if(opaque->avctx->extradata[0] == 0 && opaque->avctx->extradata[1] == 0 && opaque->avctx->extradata[2] == 0
&& opaque->avctx->extradata[3] == 1 && opaque->avctx->extradata[4] == 9 && opaque->avctx->extradata[5] == 240){
if(opaque->codecpar->extradata[0] == 0 && opaque->codecpar->extradata[1] == 0 && opaque->codecpar->extradata[2] == 0
&& opaque->codecpar->extradata[3] == 1 && opaque->codecpar->extradata[4] == 9 && opaque->codecpar->extradata[5] == 240){
for(int i=6;iavctx->extradata_size-4;i++){
if(opaque->avctx->extradata[i] == 0 && opaque->avctx->extradata[i+1] == 0 && opaque->avctx->extradata[i+2] == 0
&& opaque->avctx->extradata[i+3] == 1){
if(opaque->avctx->extradata[i+4] == 103){
if(opaque->codecpar->extradata[i] == 0 && opaque->codecpar->extradata[i+1] == 0 && opaque->codecpar->extradata[i+2] == 0
&& opaque->codecpar->extradata[i+3] == 1){
if(opaque->codecpar->extradata[i+4] == 103){
spsIndex = i;
ALOGE("AMediaFormat find sps = %d",spsIndex);
}else if(opaque->avctx->extradata[i+4] == 104){
}else if(opaque->codecpar->extradata[i+4] == 104){
ppsIndex = i;
ALOGE("AMediaFormat find pps = %d",ppsIndex);
}
@@ -275,11 +274,11 @@ static int recreate_format_l(JNIEnv *env, IJKFF_Pipenode *node)
if(ppsIndex > 0 && spsIndex < ppsIndex){
length = ppsIndex-spsIndex;
}else{
length = opaque->avctx->extradata_size-spsIndex;
length = opaque->codecpar->extradata_size-spsIndex;
}
uint8_t *convert_buffer = (uint8_t *)calloc(1, length);
memcpy( convert_buffer, opaque->avctx->extradata+spsIndex, length);
memcpy( convert_buffer, opaque->codecpar->extradata+spsIndex, length);
SDL_AMediaFormat_setBuffer(opaque->input_aformat, "csd-0", convert_buffer, length);
free(convert_buffer);
一、SPS和PPS文档说明
ByteBuffer spsb = videoEncodec.getOutputFormat().getByteBuffer("csd-0");
byte[] sps = new byte[spsb.remaining()];
spsb.get(sps, 0, sps.length);
ByteBuffer ppsb = videoEncodec.getOutputFormat().getByteBuffer("csd-1");
byte[] pps = new byte[ppsb.remaining()];
ppsb.get(pps, 0, pps.length);
2、异步方式
@Override
public void onOutputFormatChanged(@NonNull MediaCodec codec, @NonNull MediaFormat format) {
MediaFormat outputFormat = codec.getOutputFormat();
SPS = outputFormat.getByteBuffer("csd-0").array();
PPS = outputFormat.getByteBuffer("csd-1").array();
Log.e(TAG," onOutputFormatChanged SPS "+ CommonUtils.byteToHex(SPS));
Log.e(TAG," onOutputFormatChanged PPS "+CommonUtils.byteToHex(PPS));
}
四、对应的sps、pps、I帧、P帧等数据
1、sps、pps
sps:000000016742ffffffc01effffffda05ffffffc145ffffff97ffffff8078402150
pps:0000000168ffffffce3cffffff80
2、I帧
data:0000000165ffffffb80010ffffffa413ffffffffffffffe5ffffffc3ffffffd31239695affffffabffffffb0340a
3、P帧
data:0000000161ffffffe9ffffffab13ffffffcd72ffffffdbffffffe5ffffffe25f5d7e64ffffff9ffffffff33affffffebffffffbd
总结:编码器编出来的数据首帧、sps、pps、I帧、P帧等顺序
利用MediaCodec 获取视频的sps pps 和视频数据_we1less的博客-CSDN博客