提交 7b4f04aa 编写于 作者: C chodison 提交者: Zhang Rui

android/mediacodec: add function to support H265/HEVC.

Signed-off-by: NZhang Rui <bbcallen@gmail.com>
上级 f4e6b535
......@@ -32,6 +32,7 @@
#include "ijksdl/android/ijksdl_vout_android_nativewindow.h"
#include "ijksdl/android/ijksdl_vout_overlay_android_mediacodec.h"
#include "h264_nal.h"
#include "hevc_nal.h"
#define AMC_USE_AVBITSTREAM_FILTER 0
#ifndef AMCTRACE
......@@ -324,6 +325,8 @@ static int feed_input_buffer(JNIEnv *env, IJKFF_Pipenode *node, int64_t timeUs,
goto fail;
}
opaque->avctx = opaque->decoder->avctx;
if (!d->packet_pending || d->queue->serial != d->pkt_serial) {
#if AMC_USE_AVBITSTREAM_FILTER
#else
......@@ -399,6 +402,7 @@ static int feed_input_buffer(JNIEnv *env, IJKFF_Pipenode *node, int64_t timeUs,
d->pkt_temp.data[6],
d->pkt_temp.data[7]);
#endif
if (opaque->avctx->codec_id == AV_CODEC_ID_H264 || opaque->avctx->codec_id == AV_CODEC_ID_HEVC) {
convert_h264_to_annexb(d->pkt_temp.data, d->pkt_temp.size, opaque->nal_size, &convert_state);
int64_t time_stamp = d->pkt_temp.pts;
if (!time_stamp && d->pkt_temp.dts)
......@@ -408,6 +412,7 @@ static int feed_input_buffer(JNIEnv *env, IJKFF_Pipenode *node, int64_t timeUs,
} else {
time_stamp = 0;
}
}
#if 0
AMCTRACE("input[%d][%d][%lld,%lld (%d, %d) -> %lld] %02x%02x%02x%02x%02x%02x%02x%02x", (int)d->pkt_temp.size,
(int)opaque->nal_size,
......@@ -996,8 +1001,13 @@ IJKFF_Pipenode *ffpipenode_create_video_decoder_from_android_mediacodec(FFPlayer
opaque->mcc.profile = opaque->avctx->profile;
opaque->mcc.level = opaque->avctx->level;
break;
case AV_CODEC_ID_HEVC:
strcpy(opaque->mcc.mime_type, SDL_AMIME_VIDEO_HEVC);
opaque->mcc.profile = opaque->avctx->profile;
opaque->mcc.level = opaque->avctx->level;
break;
default:
ALOGE("%s:create: not H264\n", __func__);
ALOGE("%s:create: not H264 or H265/HEVC, codec_id:%d \n", __func__, opaque->avctx->codec_id);
goto fail;
}
......@@ -1022,12 +1032,21 @@ IJKFF_Pipenode *ffpipenode_create_video_decoder_from_android_mediacodec(FFPlayer
ALOGI("AMediaFormat: %s, %dx%d\n", opaque->mcc.mime_type, opaque->avctx->width, opaque->avctx->height);
opaque->input_aformat = SDL_AMediaFormatJava_createVideoFormat(env, opaque->mcc.mime_type, opaque->avctx->width, opaque->avctx->height);
if (opaque->avctx->extradata && opaque->avctx->extradata_size > 0) {
if (opaque->avctx->codec_id == AV_CODEC_ID_H264 && opaque->avctx->extradata[0] == 1) {
if ((opaque->avctx->codec_id == AV_CODEC_ID_H264 || opaque->avctx->codec_id == AV_CODEC_ID_HEVC)
&& opaque->avctx->extradata[0] == 1) {
#if AMC_USE_AVBITSTREAM_FILTER
opaque->bsfc = av_bitstream_filter_init("h264_mp4toannexb");
if (!opaque->bsfc) {
ALOGE("Cannot open the h264_mp4toannexb BSF!\n");
goto fail;
if (opaque->avctx->codec_id == AV_CODEC_ID_H264) {
opaque->bsfc = av_bitstream_filter_init("h264_mp4toannexb");
if (!opaque->bsfc) {
ALOGE("Cannot open the h264_mp4toannexb BSF!\n");
goto fail;
}
} else {
opaque->bsfc = av_bitstream_filter_init("hevc_mp4toannexb");
if (!opaque->bsfc) {
ALOGE("Cannot open the hevc_mp4toannexb BSF!\n");
goto fail;
}
}
opaque->orig_extradata_size = opaque->avctx->extradata_size;
......@@ -1049,11 +1068,20 @@ IJKFF_Pipenode *ffpipenode_create_video_decoder_from_android_mediacodec(FFPlayer
ALOGE("%s:sps_pps_buffer: alloc failed\n", __func__);
goto fail;
}
if (0 != convert_sps_pps(opaque->avctx->extradata, opaque->avctx->extradata_size,
convert_buffer, convert_size,
&sps_pps_size, &opaque->nal_size)) {
ALOGE("%s:convert_sps_pps: failed\n", __func__);
goto fail;
if (opaque->avctx->codec_id == AV_CODEC_ID_H264) {
if (0 != convert_sps_pps(opaque->avctx->extradata, opaque->avctx->extradata_size,
convert_buffer, convert_size,
&sps_pps_size, &opaque->nal_size)) {
ALOGE("%s:convert_sps_pps: failed\n", __func__);
goto fail;
}
} else {
if (0 != convert_hevc_nal_units(opaque->avctx->extradata, opaque->avctx->extradata_size,
convert_buffer, convert_size,
&sps_pps_size, &opaque->nal_size)) {
ALOGE("%s:convert_hevc_nal_units: failed\n", __func__);
goto fail;
}
}
SDL_AMediaFormat_setBuffer(opaque->input_aformat, "csd-0", convert_buffer, sps_pps_size);
for(int i = 0; i < sps_pps_size; i+=4) {
......
/*
* Copyright (c) 2015 Chodison Chen <c_soft_dev@163.com>
*
* This file is part of ijkPlayer.
*
* ijkPlayer is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* ijkPlayer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with ijkPlayer; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <limits.h>
#include "libavcodec/avcodec.h"
#include "ijksdl/ijksdl_log.h"
/* Inspired by libavcodec/hevc.c */
int convert_hevc_nal_units(const uint8_t *p_buf,uint32_t i_buf_size,
uint8_t *p_out_buf,uint32_t i_out_buf_size,
uint32_t *p_sps_pps_size,uint32_t *p_nal_size)
{
int i, num_arrays;
const uint8_t *p_end = p_buf + i_buf_size;
uint32_t i_sps_pps_size = 0;
if( i_buf_size <= 3 || ( !p_buf[0] && !p_buf[1] && p_buf[2] <= 1 ) )
return -1;
if( p_end - p_buf < 23 )
{
ALOGE( "Input Metadata too small" );
return -1;
}
p_buf += 21;
if( p_nal_size )
*p_nal_size = (*p_buf & 0x03) + 1;
p_buf++;
num_arrays = *p_buf++;
for( i = 0; i < num_arrays; i++ )
{
int type, cnt, j;
if( p_end - p_buf < 3 )
{
ALOGE( "Input Metadata too small" );
return -1;
}
type = *(p_buf++) & 0x3f;
(void)(type);
cnt = p_buf[0] << 8 | p_buf[1];
p_buf += 2;
for( j = 0; j < cnt; j++ )
{
int i_nal_size;
if( p_end - p_buf < 2 )
{
ALOGE( "Input Metadata too small" );
return -1;
}
i_nal_size = p_buf[0] << 8 | p_buf[1];
p_buf += 2;
if( i_nal_size < 0 || p_end - p_buf < i_nal_size )
{
ALOGE( "NAL unit size does not match Input Metadata size" );
return -1;
}
if( i_sps_pps_size + 4 + i_nal_size > i_out_buf_size )
{
ALOGE( "Output buffer too small" );
return -1;
}
p_out_buf[i_sps_pps_size++] = 0;
p_out_buf[i_sps_pps_size++] = 0;
p_out_buf[i_sps_pps_size++] = 0;
p_out_buf[i_sps_pps_size++] = 1;
memcpy(p_out_buf + i_sps_pps_size, p_buf, i_nal_size);
p_buf += i_nal_size;
i_sps_pps_size += i_nal_size;
}
}
*p_sps_pps_size = i_sps_pps_size;
return 0;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册