-
Notifications
You must be signed in to change notification settings - Fork 73
KSC265codec_sdk_doc
[TOC]
编解码器接口公用基本数据类型, 位于qy265def.h
// ****************************************
// error type
// ****************************************
enum
{
QY_OK = (0x00000000), // Success codes
QY_FAIL = (0x80000001), // Unspecified error
QY_OUTOFMEMORY = (0x80000002), // Ran out of memory
QY_POINTER = (0x80000003), // Invalid pointer
QY_NOTSUPPORTED = (0x80000004),// NOT support feature encoutnered
QY_AUTH_INVALID = (0x80000005), // authentication invalid
QY_SEARCHING_ACCESS_POINT = (0x00000001), // in process of searching first access point
QY_REF_PIC_NOT_FOUND = (0x00000007), // reference picture not found, can be ignored
QY_BITSTREAM_ERROR = (0x00000009), // detecting bitstream error, can be ignored
};
错误码分为三大类状态:
- 等于0: QY_OK,表示完全正常
- 大于0: 虽然当前不能正常解码,但解码器本身并没有出错。比如还没有找到有效的随机访问点,而当前给解码器的NALS并不是随机访问点(QY_SEARCHING_ACCESS_POINT);比如找不到参考帧,或者检测出码流比特错误,依靠解码器自身的鲁棒性,后续解码可以照常进行
- 小于0: 表示解码器本身发生了一些异常和错误,比如遇到不支持的feature,或者内存耗尽等
typedef void (*QYLogPrintf)(const char* msg);
void QY265SetLogPrintf ( QYLogPrintf pFuncCB);
如果没有设置输出日志回调函数,编解码器android默认输出到logcat,其他平台默认到标准输出。 可以用自定义输出日志函数QYLogPrintf pFuncCB代替编解码器默认输出日志函数。
QY265编码器输入视频源为YUV4:2:0 8bit, 输出符合HEVC/H.265 main profile规范的码流. 接口文件为qy265enc.h
void* QY265EncoderOpen(QY265EncConfig* pCfg, int *errorCode);
- 功能:创建一个编码器实例
- 返回值:编码器实例的指针
- 参数:
- QY265EncConfig* pCfg 编码器基本配置参数
- int *errorCode 返回错误码
###编码器基本配置参数
// ****************************************
// base configuration
// ****************************************
//app type
typedef enum QY265Tune_tag{
QY265TUNE_DEFAULT = 0,
QY265TUNE_SELFSHOW = 1,
QY265TUNE_GAME = 2,
QY265TUNE_MOVIE = 3,
QY265TUNE_SCREEN = 4
}QY265Tune;
typedef enum QY265Preset_tag{
QY265PRESET_SUPERFAST = 0,
QY265PRESET_VERYFAST = 1,
QY265PRESET_FAST = 2,
QY265PRESET_MEDIUM = 3,
QY265PRESET_SLOW = 4,
QY265PRESET_VERYSLOW = 5,
QY265PRESET_PLACEBO = 6,
}QY265Preset;
typedef enum QY265Latency_tag{
QY265LATENCY_ZERO = 0,
QY265LATENCY_LOWDELAY = 1,
QY265LATENCY_LIVESTREMING = 2,
QY265LATENCY_OFFLINE = 3,
}QY265Latency;
//base configuration
typedef struct QY265EncConfig{
void* pAuth; //QYAuth, invalid if don't need aksk auth
QY265Tune tune; //
QY265Preset preset;
QY265Latency latency;
int iHeaderBeforeKeyframe; //whether output vps,sps,pps before key frame, default 1. dis/enable 0/1
int picWidth; // input frame width
int picHeight; // input frame height
double frameRate; // input frame rate
int bframes; // num of bi-pred frames, -1: using default
int temporalLayer; // works with QY265LATENCY_ZERO, separate P frames into temporal layers, 0 or 1
int rc; // rc type 0 disable,1 cbr,2 abr,3 crf, default 2
int bitrateInkbps; // target bit rate in kbps, valid when rctype is cbr abd vbr
int vbv_buffer_size; // buf size of vbv
int vbv_max_rate; // max rate of vbv
int qp; // valid when rctype is disable, default 26
int crf; // valid when rctype is crf,default 24
int iIntraPeriod; // I-Frame period
int qpmin; //minimal qp, valid when rc != 0, 0~51
int qpmax; //maximal qp, valid when rc != 0, 1~51, qpmax = 0 means 51
//* Execute Properties
int iWavefront; //enable wave front parallel
int enFrameParallel; //enable frame parallel
int threads; // number of threads used in encoding ( for wavefront, frame parallel, or enable both )
//* vui_parameters
//vui_parameters_present_flag equal to 1 specifies that the vui_parameters() syntax in struct vui should set by usr
int vui_parameters_present_flag;
struct{
/* video_signal_type_present_flag. If this is set then
* video_format, video_full_range_flag and colour_description_present_flag
* will be added to the VUI. The default is false */
int video_signal_type_present_flag;
/* Video format of the source video. 0 = component, 1 = PAL, 2 = NTSC,
* 3 = SECAM, 4 = MAC, 5 = unspecified video format is the default */
int video_format;
/* video_full_range_flag indicates the black level and range of the luma
* and chroma signals as derived from E′Y, E′PB, and E′PR or E′R, E′G,
* and E′B real-valued component signals. The default is false */
int video_full_range_flag;
/* colour_description_present_flag in the VUI. If this is set then
* color_primaries, transfer_characteristics and matrix_coeffs are to be
* added to the VUI. The default is false */
int colour_description_present_flag;
/* colour_primaries holds the chromacity coordinates of the source
* primaries. The default is 2 */
int colour_primaries;
/* transfer_characteristics indicates the opto-electronic transfer
* characteristic of the source picture. The default is 2 */
int transfer_characteristics;
/* matrix_coeffs used to derive the luma and chroma signals from
* the red, blue and green primaries. The default is 2 */
int matrix_coeffs;
}vui;
//* debug
int logLevel;
int calcPsnr; //0:not calc psnr; 1: print total psnr; 2: print each frame
int shortLoadingForPlayer; //reduce b frames after I frame, for shorting the loading time of VOD for some players
}QY265EncConfig;
void* pAuth: 鉴权信息, 不做鉴权时忽略。做鉴权在下一节说明 QY265Tune tune: 应用场景. 目前使用default即可 QY265Preset preset: 速度档次. 支持从superfast到placebo, 默认值为veryfast. QY265Latency latency: 延迟档次, 默认值为QY265LATENCY_OFFLINE.
QY265LATENCY_ZERO = 0 应用于实时通信, 零延迟.
QY265LATENCY_LOWDELAY = 1 应用于实时通信, 低延迟
QY265LATENCY_LIVESTREMING = 2 应用于实时直播, 只有几帧的延迟
QY265LATENCY_OFFLINE = 3 应用于离线, 不考虑延迟大小
int bHeaderBeforeKeyframe:是否在关键帧前面都插入参数集vps/sps/pps. 0:否, 1:是. 默认值为1, 表示插入参数集. int picWidth, picHeight:输入图像分辨率. double frameRate:输入帧率. int bframes: 相邻两个前向参考图像间最大使用的B帧数目. 不配置或值为-1时, 表示使用默认数目7. 目前支持0,1,3,7. int temporalLayer: 是否使用时间分级, 在QY265LATENCY_ZERO和QY265LATENCY_LOWDELAY两个延迟档次使用. 0:关闭, 1:打开. 默认值为0, 关闭. int rc:0: 定QP;1: CBR; 2: ABR; 3: CRF, 默认值为1, CBR. int bitrateInkbps:目标码率, 单位为kbps, 当rc = 1, 2时有效. 默认值为500. int qp:量化参数, 当rc=0时有效, 默认值为30. int qpmin: 码率控制过程中, 帧级使用的最小qp, 当rc不等于0时有效, 默认值0. int qpmax:码率控制过程中, 帧级使用的最大qp, 当rc不等于0时有效, 默认值51. int vbv_buffer_size:码率控制过程中, vbv缓冲区大小, 单位为kbits. int vbv_max_rate:码率控制过程中, vbv缓冲区内的编码码率上限, 单位为kbps. int crf:作用类似于qp, rc=3时有效, 默认值30. int iIntraPeriod:关键帧间隔, 单位为帧数, 默认值256. int threads:线程数, =0表示自动识别CPU核数;>0表示线程数目 int enWavefront:是否启动wpp并行. 默认配置:threads值为0时, 启动;threads值为1时, 关闭;threads值为其他值时, 智能计算. int enFrameParallel:是否启动帧级并行. 默认配置:threads值为0时, 启动;threads值为1时, 关闭;threads值为其他值时, 智能计算. int vui_parameters_present_flag: 不使用VUI相关配置时, 设为0, 否则设为1. 默认值0. int logLevel:默认值为0. 其他取值为, -1: dbg; 0: info; 1:warn; 2:err; 3:fatal. int shortLoadingForPlayer: 缩短播放器首次loading数据时间,默认值0. 设置为1有效。
void QY265EncoderClose(void* pEncoder);
- 功能:销毁一个编码器实例
- 返回值:无
- 参数:编码器实例的指针
int QY265EncoderEncodeFrame(void* pEncoder, QY265Nal** pNals, int* iNalCount, QY265Picture* pInpic, QY265Picture* pOutpic, int bForceLogo);
- 功能:编码一帧YUV图像
- 返回值:错误码, 0表示正常
- 参数:
- void* pEncoder 编码器实例的指针
- QY265Nal** pNals编码生成的NAL单元的指针, pNals[i]表示第i个NAL单元的指针
- int* iNalCount 编码生成的NAL单元的数目
- QY265Picture* pInpic输入YUV图像结构体指针, 与输出pNals不同步
- QY265Picture* pOutpic输出图像帧信息, 作为输出pNals的辅助信息, 与输出pNals同步. 仅为参考使用, 丢弃不影响正常编码
- int bForceLogo, 调试使用, 恒为0
typedef struct QY265Nal
{
int naltype;
int tid;
int iSize;
unsigned int pts;
unsigned char* pPayload;
}QY265Nal;
int naltype:符合标准规定的NAL类型 int tid:时间层级, 0为最关键的层级, 值大的时间层级会使用值小的时间层级作参考 int iSize:NAL单元的大小, 单位为字节. 包含起始码. unsigned int pts:显示时间标签 unsigned char* pPayload:NAL数据的起始指针
// input frame data and info
typedef struct QY265YUV{
int iWidth; // input frame width
int iHeight; // input frame height
unsigned char* pData[3]; // input frame Y U V
int iStride[3]; // stride for Y U V
}QY265YUV;
// input frame data and info
typedef struct QY265Picture{
int iSliceType; // specified by output pictures
int poc; // ignored on input
long long pts;
long long dts;
QY265YUV* yuv;
}QY265Picture;
int iWidth, iHeight:图像帧的宽高 unsigned char* pData[3]:YUV数据Buffer的起始地址 int iStride[3]:YUV数据Buffer像素行间的步长, 大于等于宽度 int iSliceType:图像slice类型, 输入时不用指定, 默认为0即可 int poc:图像POC值, 输入时不用指定 unsigned int pts:显示时间标签 unsigned int dts:解码时间标签, 输入时不用指定
int QY265EncoderEncodeHeaders(void* pEncoder,QY265Nal** pNals,int* iNalCount);
- 功能:编码vps/sps/pps参数集
- 返回值:错误码, 0表示正常
- 参数:
- void* pEncoder 编码器实例的指针
- QY265Nal** pNals编码生成的NAL单元的指针, pNals[i]表示第i个NAL单元的指针
- int* iNalCount 编码生成的NAL单元的数目
void QY265EncoderKeyFrameRequest(void* pEncoder);
- 功能:发起编码关键帧的请求, 编码器将会在下一次调用QY265EncoderEncodeFrame时编码关键帧
- 返回值:无
- 参数:void* pEncoder 编码器实例的指针
int QY265EncoderDelayedFrames(void* pEncoder);
- 功能:查询编码器延迟尚未编码的帧数, 只在序列结束时使用, 如果返回值大于0, 说明还有延迟的帧尚未完成编码, 需要继续调用QY265EncoderEncodeFrame直至所有帧完成编码
- 返回值:延迟帧数目, 等于0表示已经编完
- 参数:void* pEncoder 编码器实例的指针
int QY265ConfigDefault(QY265EncConfig* pConfig, QY265Preset preset, QY265Tune tune, QY265Latency latency);
- 功能:通过指定preset, tune, latency生成pConfig默认配置参数
- 返回值: 错误码
- 参数:
- QY265EncConfig* pConfig: 基本配置参数指针
- QY265Preset preset: 指定速度档次
- QY265Tune tune: 指定应用场景
- QY265Latency latency: 指定延迟档次
void QY265EncoderReconfig(void* pEncoder,QY265EncConfig* pCfg);
- 功能:改变基本配置参数,主要用于码率,帧率的调整。
QY265解码器支持符合HEVC/H.265 main profile规范的码流. 接口文件为qy265dec.h
void* QY265DecoderCreate(QY265DecConfig* pDecConfig, int * pStat);
- 功能:创建一个解码器实例
- 返回值:解码器实例的指针
- 参数:
- QY265DecConfig* pDecConfig 解码器基本配置参数
- int* pStat 返回错误码, 0表示正常
// config parameters for Decoder
typedef struct QY265DecConfig {
void* pAuth; //QYAuth, invalid if don't need aksk auth
int threads; // number of threads used in decoding (0: auto)
bool bEnableOutputRecToFile; // For debug: write reconstruct YUV to File
char* strRecYuvFileName; // For debug: file name of YUV
// when bEnableOutputRecToFile = 1
int logLevel; //For debug: log level
}QY265DecConfig;
void* pAuth: 鉴权信息, 不做鉴权时忽略 int threads:线程数, =0表示自动识别CPU核数;>0表示线程数目 bool bEnableOutputRecToFile 是否输出重建YUV文件, 调试使用 char* strRecYuvFileName 输出重建YUV文件名, bEnableOutputRecToFile=1时有效, 调试使用 int logLevel 默认为0
void QY265DecoderDestroy(void* pDecoder);
- 功能:销毁一个解码器实例
- 返回值:无
- 参数:解码器实例的指针
void QY265DecoderSetDecConfig(void *pDecoder, QY265DecConfig* pDecConfig, int * pStat);
- 功能:解码器执行过程中, 改变配置参数
- 返回值:无
- 参数:
- void* pDecoder 解码器实例的指针
- QY265DecConfig* pCfg解码器基本配置参数
- int* pStat 返回错误码, 0表示正常
void QY265DecodeFrame(void *pDecoder, unsigned char* pData, int iLen, int * pStat, const long long pts);
- 功能:解码一个或多个NAL单元, 必须是整数个NAL单元
- 返回值:无
- 参数:
- void* pDecoder 解码器实例的指针
- unsigned char* pData 码流数据起始地址
- int iLen 码流数据长度, 单位为字节
- const long long pts NAL单元对应显示时间标签
void QY265DecoderGetDecodedFrame(void *pDecoder, QY265Frame* pFrame, int * pStat, int bForceLogo);
- 功能:获取解码输出, 与QY265DecodeFrame异步. 与QY265DecoderReturnFrame配套使用, 如果获取到有效输出帧, 在使用完毕后必须调用QY265DecoderReturnFrame归还
- 返回值:无
- 参数:
- void* pDecoder 解码器实例的指针
- QY265Frame* pFrame 解码输出帧信息, 详见以下
- int* pStat 返回错误码, 0表示正常
// information of decoded frame
typedef struct QY265FrameInfo {
int nWidth; // frame width
int nHeight; // frame height
long long pts; // time stamp
bool bIllegalStream; // input bit stream is illegal
}QY265FrameInfo;
// decoded frame with data and information
typedef struct QY265Frame {
int bValid; //if == 0, no more valid output frame
unsigned char* pData[3]; // Y U V
short iStride[3]; // stride for each component
QY265FrameInfo frameinfo;
}QY265Frame;
int nWidth nHeight:解码输出帧的图像宽高 long long pts:解码输出帧对应显示时间标签 bool bIllegalStream:just ignored int bValid:是否获取到有效解码输出帧, 1为有效 unsigned char* pData[3] 解码输出帧存, YUV buffer起始地址 short iStride[3] 解码输出帧存, YUV buffer像素行步长
void QY265DecoderReturnDecodedFrame( void *pDecoder, QY265Frame* pFrame);
- 功能:归还解码输出帧存, 与QY265DecoderGetOutput 配套使用, 获取到的有效帧存在使用完毕后, 调用本函数归还帧存.
- 返回值:无
- 参数:
- void* pDecoder 解码器实例的指针
- QY265Frame* pFrame 解码输出帧信息, 应与QY265DecoderGetOutput获取到的有效帧信息相同
void QY265DecodeFlush(void *pDecoder, int bClearCachedPics, int * pStat);
- 功能:因为解码NAL单元与获取解码输出为异步关系, 所以解码器中可能存在剩余尚未解码完成的若干NAL单元. 调用本函数将使解码器完成所有已经输入的NAL单元的解码. 然后配合QY265DecoderGetOutput获取剩余的解码输出. 一般在码流结束或者播放器拖曳时使用.
- 返回值:无
- 参数:
- void* pDecoder 解码器实例的指针
- int bClearCachedPics 是否清除缓冲的图像. 在码流结束时, 置为false, 不清除, 得到所有输出帧;在播放器拖曳或其他情况下, 置为true, 清除之前的图像帧, 重新开始
- int* pStat 返回错误码, 0表示正常
#鉴权接口说明 如上所述,编码器基本配置参数QY265EncConfig以及解码器基本配置参数QY265DecConfig中都有void* pAuth变量用于鉴权。 在不同鉴权方式时,将不同的鉴权结构体指针赋予pAuth来实施鉴权认证。鉴权相关的接口定义在qyauth_env.h头文件。
服务端鉴权通过读取本地密钥文件获得认证,pAuth指向正确的密钥文件即可。详细的鉴权说明见《KSC265编解码器鉴权说明文档》。
服务端鉴权需要-DKSAUTH_PRIVATE_AUTH=1 或者将在qyauth_env.h中将 KSAUTH_PRIVATE_AUTH 的默认值改为1配合ffmpeg wrapper文件使用,因为qyauth_env.h和ffmpeg wrapper文件都是各个平台共用的,只有服务端需要KSAUTH_PRIVATE_AUTH=1,因此我们默认写为0了。
- 创建示例
QY265EncConfig cfg;
cfg.pAuth = "/home/usrXXX/ks265.key";
//...
int errCode = 0;
void* encoder = QY265EncoderOpen(&cfg, &errCode);
if(errCode == QY_AUTH_INVALID){
//...
}
- 设置报警回调
typedef void (*QYAuthWarning)();
void QY265SetAuthWarning ( QYAuthWarning pFuncCB);
该接口位于qy265def.h。在异步连接license server通讯故障时,调用用户自定义的回调函数产生报警。
android和ios移动端鉴权需要读取有效包名。
编译的时候需要添加 -framework Foundation -framework UIKit 编译选项。
pAuth传入NULL指针即可。
#include <jni.h>
typedef struct _TCounterEnv
{
JavaVM *jvm;
jobject context;
}TCounterEnv;
android需要传入jvm和context,将TCounterEnv实例的指针赋值给编解码器基本配置参数QY265EncConfig或QY265DecConfig的pAuth指针。使用示例如下
// config config.pAuth for Decoder
TCounterEnv* tCounterEnv = (TCounterEnv*) malloc(sizeof(TCounterEnv));
tCounterEnv->context = context;
env->GetJavaVM(&tCounterEnv->jvm);
QY265DecConfig config;
config.bEnableOutputRecToFile = false;
config.logLevel = 0;
config.pAuth = tCounterEnv;
int ret;
QY265DecoderCreate(&config, &ret);
__android_log_print(ANDROID_LOG_ERROR, "qyauth", "ret = %d", ret);
- TCounterEnv使用全局静态变量
上述示例代码中,context需要传入。为方便起见,TCounterEnv建议使用全局静态变量,以下为一个jni文件的例子
TCounterEnv tenv;
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
LOGD( "onload " );
tenv.jvm = vm;
return JNI_VERSION_1_4;
}
extern "C" JNIEXPORT void JNICALL Java_net_qyvideo_android_qyffdemo_MainActivity_setAppContext(JNIEnv* env, jobject thiz, jobject context){
tenv.context = env->NewGlobalRef(context);
}
JNI_OnLoad的时候set jvm; 此外添加一个jni函数set context,该函数在java里面提前调用:
setAppContext(this.getApplicationContext());
setAppContext设置的Context最好使用APP的Context,而不要使用Activity的Context
- ffmpeg中使用
ffmpeg中,在open_video之前将TCounterEnv实例的指针传给opaque:
AVCodecContext *c = video_st.st->codec;
c->opaque = &tenv;
open_video(oc, video_codec, &video_st, opt_video);
我们自带的ffmpeg wrapper文件会将opaque的指针赋给cfg的pAuth,如libqy265dec.c中的代码片段(这段代码只用作说明,用户不用修改):
static av_cold int hevc_decode_init(AVCodecContext *avctx) {
QY265Context *ctx = avctx->priv_data;
//...
ctx->params->pAuth = avctx->opaque;
ctx->m_decoder = QY265DecoderCreate(ctx->params, &ret);
ffmpeg中使用解码器时,有avformat_find_stream_info的过程会打开解码器,也涉及到鉴权,需要在libavformat/utils.c的avformat_find_stream_info函数中//Try to just open decoders
的avcodec_open2之前判断是HEVC时设置一下用于鉴权的指针:
// Try to just open decoders, in case this is enough to get parameters.
if (!has_codec_parameters(st, NULL) && st->request_probe <= 0) {
if (codec && !st->codec->codec){
//*** add code here
if(st->codecpar->codec_id == AV_CODEC_ID_HEVC){
avctx->opaque = &tenv;
}
//*** add code finish
if (avcodec_open2(st->codec, codec, options ? &options[i] : &thread_opt) < 0)
av_log(ic, AV_LOG_WARNING, "Failed to open codec in av_find_stream_info\n");
}
}