mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 10:40:05 +08:00
全面更新整理c sdk
This commit is contained in:
parent
9736badcea
commit
cb0e5c6c57
@ -14,24 +14,21 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32) && defined(_MSC_VER)
|
||||||
|
# ifndef MediaKitApi_STATIC
|
||||||
#ifndef MediaKitApi_STATIC
|
# if defined(MediaKitApi_EXPORTS)
|
||||||
#if defined(MediaKitApi_EXPORTS)
|
# define API_EXPORT __declspec(dllexport)
|
||||||
#define API_EXPORT __declspec(dllexport)
|
# else
|
||||||
#else
|
# define API_EXPORT __declspec(dllimport)
|
||||||
#define API_EXPORT __declspec(dllimport)
|
# endif
|
||||||
#endif
|
# define API_CALL __cdecl
|
||||||
|
# else
|
||||||
#define API_CALL __cdecl
|
# define API_EXPORT
|
||||||
|
# define API_CALL
|
||||||
|
# endif
|
||||||
#else
|
#else
|
||||||
#define API_EXPORT
|
# define API_EXPORT
|
||||||
#define API_CALL
|
# define API_CALL
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
#define API_EXPORT
|
|
||||||
#define API_CALL
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
123
api/include/mk_frame.h
Normal file
123
api/include/mk_frame.h
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_MK_FRAME_H
|
||||||
|
#define ZLMEDIAKIT_MK_FRAME_H
|
||||||
|
|
||||||
|
#include "mk_common.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//是否为关键帧
|
||||||
|
#define MK_FRAME_FLAG_IS_KEY (1 << 0)
|
||||||
|
//是否为配置帧(sps/pps/vps等)
|
||||||
|
#define MK_FRAME_FLAG_IS_CONFIG (1 << 1)
|
||||||
|
//是否可丢弃的帧(sei/aud)
|
||||||
|
#define MK_FRAME_FLAG_DROP_ABLE (1 << 2)
|
||||||
|
//是否不可单独解码的帧(多slice的非vcl帧)
|
||||||
|
#define MK_FRAME_FLAG_NOT_DECODE_ABLE (1 << 3)
|
||||||
|
|
||||||
|
//codec id常量定义
|
||||||
|
API_EXPORT extern const int MKCodecH264;
|
||||||
|
API_EXPORT extern const int MKCodecH265;
|
||||||
|
API_EXPORT extern const int MKCodecAAC;
|
||||||
|
API_EXPORT extern const int MKCodecG711A;
|
||||||
|
API_EXPORT extern const int MKCodecG711U;
|
||||||
|
API_EXPORT extern const int MKCodecOpus;
|
||||||
|
API_EXPORT extern const int MKCodecL16;
|
||||||
|
API_EXPORT extern const int MKCodecVP8;
|
||||||
|
API_EXPORT extern const int MKCodecVP9;
|
||||||
|
API_EXPORT extern const int MKCodecAV1;
|
||||||
|
API_EXPORT extern const int MKCodecJPEG;
|
||||||
|
|
||||||
|
typedef void *mk_frame;
|
||||||
|
|
||||||
|
// 用户自定义free回调函数
|
||||||
|
typedef void(API_CALL *on_mk_frame_data_release)(void *user_data, char *ptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建frame对象,并返回其引用
|
||||||
|
* @param codec_id 编解码类型,请参考MKCodecXXX定义
|
||||||
|
* @param dts 解码时间戳,单位毫秒
|
||||||
|
* @param pts 显示时间戳,单位毫秒
|
||||||
|
* @param data 单帧数据
|
||||||
|
* @param size 单帧数据长度
|
||||||
|
* @param cb data指针free释放回调, 如果为空,内部会拷贝数据
|
||||||
|
* @param user_data data指针free释放回调用户指针
|
||||||
|
* @return frame对象引用
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_frame API_CALL mk_frame_create(int codec_id, uint32_t dts, uint32_t pts, const char *data, size_t size,
|
||||||
|
on_mk_frame_data_release cb, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 减引用frame对象
|
||||||
|
* @param frame 帧对象引用
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_frame_unref(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 引用frame对象
|
||||||
|
* @param frame 被引用的frame对象
|
||||||
|
* @return 新的对象引用
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_frame API_CALL mk_frame_ref(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取frame 编码codec类型,请参考MKCodecXXX定义
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_frame_codec_id(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取帧编码codec名称
|
||||||
|
*/
|
||||||
|
API_EXPORT const char* API_CALL mk_frame_codec_name(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 帧是否为视频
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_frame_is_video(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取帧数据指针
|
||||||
|
*/
|
||||||
|
API_EXPORT const char* API_CALL mk_frame_get_data(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取帧数据指针长度
|
||||||
|
*/
|
||||||
|
API_EXPORT size_t API_CALL mk_frame_get_data_size(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回帧数据前缀长度,譬如H264/H265前缀一般是0x00 00 00 01,那么本函数返回4
|
||||||
|
*/
|
||||||
|
API_EXPORT size_t API_CALL mk_frame_get_data_prefix_size(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取解码时间戳,单位毫秒
|
||||||
|
*/
|
||||||
|
API_EXPORT uint32_t API_CALL mk_frame_get_dts(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取显示时间戳,单位毫秒
|
||||||
|
*/
|
||||||
|
API_EXPORT uint32_t API_CALL mk_frame_get_pts(mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取帧flag,请参考 MK_FRAME_FLAG
|
||||||
|
*/
|
||||||
|
API_EXPORT uint32_t API_CALL mk_frame_get_flags(mk_frame frame);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_MK_FRAME_H
|
@ -12,6 +12,8 @@
|
|||||||
#define MK_MEDIA_H_
|
#define MK_MEDIA_H_
|
||||||
|
|
||||||
#include "mk_common.h"
|
#include "mk_common.h"
|
||||||
|
#include "mk_track.h"
|
||||||
|
#include "mk_frame.h"
|
||||||
#include "mk_events_objects.h"
|
#include "mk_events_objects.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -40,18 +42,29 @@ API_EXPORT mk_media API_CALL mk_media_create(const char *vhost, const char *app,
|
|||||||
API_EXPORT void API_CALL mk_media_release(mk_media ctx);
|
API_EXPORT void API_CALL mk_media_release(mk_media ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加视频轨道
|
* 添加音视频track
|
||||||
|
* @param ctx mk_media对象
|
||||||
|
* @param track mk_track对象,音视频轨道
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_media_init_track(mk_media ctx, mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加视频轨道,请改用mk_media_init_track方法
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param codec_id 0:CodecH264/1:CodecH265
|
* @param codec_id 0:CodecH264/1:CodecH265
|
||||||
|
* @param width 视频宽度; 在编码时才有效
|
||||||
|
* @param height 视频高度; 在编码时才有效
|
||||||
|
* @param fps 视频fps; 在编码时才有效
|
||||||
|
* @param bit_rate 视频比特率,单位bps; 在编码时才有效
|
||||||
* @param width 视频宽度
|
* @param width 视频宽度
|
||||||
* @param height 视频高度
|
* @param height 视频高度
|
||||||
* @param fps 视频fps
|
* @param fps 视频fps
|
||||||
* @return 1代表成功,0失败
|
* @return 1代表成功,0失败
|
||||||
*/
|
*/
|
||||||
API_EXPORT int API_CALL mk_media_init_video(mk_media ctx, int codec_id, int width, int height, float fps);
|
API_EXPORT int API_CALL mk_media_init_video(mk_media ctx, int codec_id, int width, int height, float fps, int bit_rate);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加音频轨道
|
* 添加音频轨道,请改用mk_media_init_track方法
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param codec_id 2:CodecAAC/3:CodecG711A/4:CodecG711U/5:OPUS
|
* @param codec_id 2:CodecAAC/3:CodecG711A/4:CodecG711U/5:OPUS
|
||||||
* @param channel 通道数
|
* @param channel 通道数
|
||||||
@ -70,7 +83,15 @@ API_EXPORT int API_CALL mk_media_init_audio(mk_media ctx, int codec_id, int samp
|
|||||||
API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx);
|
API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入单帧H264视频,帧起始字节00 00 01,00 00 00 01均可
|
* 输入frame对象
|
||||||
|
* @param ctx mk_media对象
|
||||||
|
* @param frame 帧对象
|
||||||
|
* @return 1代表成功,0失败
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_media_input_frame(mk_media ctx, mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入单帧H264视频,帧起始字节00 00 01,00 00 00 01均可,请改用mk_media_input_frame方法
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param data 单帧H264数据
|
* @param data 单帧H264数据
|
||||||
* @param len 单帧H264数据字节数
|
* @param len 单帧H264数据字节数
|
||||||
@ -81,7 +102,7 @@ API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx);
|
|||||||
API_EXPORT int API_CALL mk_media_input_h264(mk_media ctx, const void *data, int len, uint32_t dts, uint32_t pts);
|
API_EXPORT int API_CALL mk_media_input_h264(mk_media ctx, const void *data, int len, uint32_t dts, uint32_t pts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入单帧H265视频,帧起始字节00 00 01,00 00 00 01均可
|
* 输入单帧H265视频,帧起始字节00 00 01,00 00 00 01均可,请改用mk_media_input_frame方法
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param data 单帧H265数据
|
* @param data 单帧H265数据
|
||||||
* @param len 单帧H265数据字节数
|
* @param len 单帧H265数据字节数
|
||||||
@ -92,7 +113,16 @@ API_EXPORT int API_CALL mk_media_input_h264(mk_media ctx, const void *data, int
|
|||||||
API_EXPORT int API_CALL mk_media_input_h265(mk_media ctx, const void *data, int len, uint32_t dts, uint32_t pts);
|
API_EXPORT int API_CALL mk_media_input_h265(mk_media ctx, const void *data, int len, uint32_t dts, uint32_t pts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入单帧AAC音频(单独指定adts头)
|
* 输入YUV视频数据
|
||||||
|
* @param ctx 对象指针
|
||||||
|
* @param yuv yuv420p数据
|
||||||
|
* @param linesize yuv420p linesize
|
||||||
|
* @param cts 视频采集时间戳,单位毫秒
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_media_input_yuv(mk_media ctx, const char *yuv[3], int linesize[3], uint32_t cts);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入单帧AAC音频(单独指定adts头),请改用mk_media_input_frame方法
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param data 不包含adts头的单帧AAC数据,adts头7个字节
|
* @param data 不包含adts头的单帧AAC数据,adts头7个字节
|
||||||
* @param len 单帧AAC数据字节数
|
* @param len 单帧AAC数据字节数
|
||||||
@ -113,7 +143,7 @@ API_EXPORT int API_CALL mk_media_input_aac(mk_media ctx, const void *data, int l
|
|||||||
API_EXPORT int API_CALL mk_media_input_pcm(mk_media ctx, void *data, int len, uint32_t pts);
|
API_EXPORT int API_CALL mk_media_input_pcm(mk_media ctx, void *data, int len, uint32_t pts);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入单帧OPUS/G711音频帧
|
* 输入单帧OPUS/G711音频帧,请改用mk_media_input_frame方法
|
||||||
* @param ctx 对象指针
|
* @param ctx 对象指针
|
||||||
* @param data 单帧音频数据
|
* @param data 单帧音频数据
|
||||||
* @param len 单帧音频数据字节数
|
* @param len 单帧音频数据字节数
|
||||||
|
@ -24,5 +24,8 @@
|
|||||||
#include "mk_thread.h"
|
#include "mk_thread.h"
|
||||||
#include "mk_rtp_server.h"
|
#include "mk_rtp_server.h"
|
||||||
#include "mk_h264_splitter.h"
|
#include "mk_h264_splitter.h"
|
||||||
|
#include "mk_frame.h"
|
||||||
|
#include "mk_track.h"
|
||||||
|
#include "mk_transcode.h"
|
||||||
|
|
||||||
#endif /* MK_API_H_ */
|
#endif /* MK_API_H_ */
|
||||||
|
@ -12,6 +12,8 @@
|
|||||||
#define MK_PLAYER_H_
|
#define MK_PLAYER_H_
|
||||||
|
|
||||||
#include "mk_common.h"
|
#include "mk_common.h"
|
||||||
|
#include "mk_frame.h"
|
||||||
|
#include "mk_track.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -24,20 +26,11 @@ typedef void* mk_player;
|
|||||||
* @param user_data 用户数据指针
|
* @param user_data 用户数据指针
|
||||||
* @param err_code 错误代码,0为成功
|
* @param err_code 错误代码,0为成功
|
||||||
* @param err_msg 错误提示
|
* @param err_msg 错误提示
|
||||||
|
* @param tracks track列表
|
||||||
|
* @param track_count track个数
|
||||||
*/
|
*/
|
||||||
typedef void(API_CALL *on_mk_play_event)(void *user_data,int err_code,const char *err_msg);
|
typedef void(API_CALL *on_mk_play_event)(void *user_data, int err_code, const char *err_msg, mk_track tracks[],
|
||||||
|
int track_count);
|
||||||
/**
|
|
||||||
* 收到音视频数据回调
|
|
||||||
* @param user_data 用户数据指针
|
|
||||||
* @param track_type 0:视频,1:音频
|
|
||||||
* @param codec_id 0:H264,1:H265,2:AAC 3.G711A 4.G711U 5.OPUS
|
|
||||||
* @param data 数据指针
|
|
||||||
* @param len 数据长度
|
|
||||||
* @param dts 解码时间戳,单位毫秒
|
|
||||||
* @param pts 显示时间戳,单位毫秒
|
|
||||||
*/
|
|
||||||
typedef void(API_CALL *on_mk_play_data)(void *user_data,int track_type,int codec_id,void *data,size_t len, uint32_t dts,uint32_t pts);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建一个播放器,支持rtmp[s]/rtsp[s]
|
* 创建一个播放器,支持rtmp[s]/rtsp[s]
|
||||||
@ -54,7 +47,7 @@ API_EXPORT void API_CALL mk_player_release(mk_player ctx);
|
|||||||
/**
|
/**
|
||||||
* 设置播放器配置选项
|
* 设置播放器配置选项
|
||||||
* @param ctx 播放器指针
|
* @param ctx 播放器指针
|
||||||
* @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms/max_analysis_ms
|
* @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms/wait_track_ready
|
||||||
* @param val 配置项值,如果是整形,需要转换成统一转换成string
|
* @param val 配置项值,如果是整形,需要转换成统一转换成string
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_player_set_option(mk_player ctx, const char *key, const char *val);
|
API_EXPORT void API_CALL mk_player_set_option(mk_player ctx, const char *key, const char *val);
|
||||||
@ -110,67 +103,8 @@ API_EXPORT void API_CALL mk_player_set_on_result(mk_player ctx, on_mk_play_event
|
|||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_player_set_on_shutdown(mk_player ctx, on_mk_play_event cb, void *user_data);
|
API_EXPORT void API_CALL mk_player_set_on_shutdown(mk_player ctx, on_mk_play_event cb, void *user_data);
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置音视频数据回调函数
|
|
||||||
* @param ctx 播放器指针
|
|
||||||
* @param cb 回调函数指针,设置null立即取消回调
|
|
||||||
* @param user_data 用户数据指针
|
|
||||||
*/
|
|
||||||
API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb, void *user_data);
|
|
||||||
|
|
||||||
///////////////////////////获取音视频相关信息接口在播放成功回调触发后才有效///////////////////////////////
|
///////////////////////////获取音视频相关信息接口在播放成功回调触发后才有效///////////////////////////////
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
|
||||||
* @param ctx 播放器指针
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_video_codec_id(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频codec_id, vendor类型, 私有头数据 codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
|
||||||
* @param ctx 播放器指针
|
|
||||||
* @param vendor 输出厂家类型 如果是私有流 应该是H264另外还有厂家类型
|
|
||||||
* @param head 厂家SDK头数据
|
|
||||||
* @param head 厂家SDK头数据长度
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_video_codec_id_vendor_head(mk_player ctx, char* vendor, char* head, int* headLen);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频宽度
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_video_width(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频高度
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_video_height(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取视频帧率
|
|
||||||
*/
|
|
||||||
API_EXPORT float API_CALL mk_player_video_fps(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取音频codec_id -1:不存在 0:H264,1:H265,2:AAC 3.G711A 4.G711U
|
|
||||||
* @param ctx 播放器指针
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_codec_id(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取音频采样率
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_samplerate(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取音频采样位数,一般为16
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_bit(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取音频通道数
|
|
||||||
*/
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_channel(mk_player ctx);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取点播节目时长,如果是直播返回0,否则返回秒数
|
* 获取点播节目时长,如果是直播返回0,否则返回秒数
|
||||||
*/
|
*/
|
||||||
@ -193,7 +127,6 @@ API_EXPORT int API_CALL mk_player_progress_pos(mk_player ctx);
|
|||||||
*/
|
*/
|
||||||
API_EXPORT float API_CALL mk_player_loss_rate(mk_player ctx, int track_type);
|
API_EXPORT float API_CALL mk_player_loss_rate(mk_player ctx, int track_type);
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,7 +40,7 @@ API_EXPORT void API_CALL mk_proxy_player_release(mk_proxy_player ctx);
|
|||||||
/**
|
/**
|
||||||
* 设置代理播放器配置选项
|
* 设置代理播放器配置选项
|
||||||
* @param ctx 代理播放器指针
|
* @param ctx 代理播放器指针
|
||||||
* @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms/max_analysis_ms
|
* @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms
|
||||||
* @param val 配置项值,如果是整形,需要转换成统一转换成string
|
* @param val 配置项值,如果是整形,需要转换成统一转换成string
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_proxy_player_set_option(mk_proxy_player ctx, const char *key, const char *val);
|
API_EXPORT void API_CALL mk_proxy_player_set_option(mk_proxy_player ctx, const char *key, const char *val);
|
||||||
|
@ -60,7 +60,7 @@ API_EXPORT void API_CALL mk_pusher_release(mk_pusher ctx);
|
|||||||
/**
|
/**
|
||||||
* 设置推流器配置选项
|
* 设置推流器配置选项
|
||||||
* @param ctx 推流器指针
|
* @param ctx 推流器指针
|
||||||
* @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms/max_analysis_ms
|
* @param key 配置项键,支持 net_adapter/rtp_type/rtsp_user/rtsp_pwd/protocol_timeout_ms/media_timeout_ms/beat_interval_ms
|
||||||
* @param val 配置项值,如果是整形,需要转换成统一转换成string
|
* @param val 配置项值,如果是整形,需要转换成统一转换成string
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_pusher_set_option(mk_pusher ctx, const char *key, const char *val);
|
API_EXPORT void API_CALL mk_pusher_set_option(mk_pusher ctx, const char *key, const char *val);
|
||||||
|
@ -17,6 +17,25 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
///////////////////////////////////////////Buffer::Ptr/////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef void *mk_buffer;
|
||||||
|
typedef void(API_CALL *on_mk_buffer_free)(void *user_data, void *data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建buffer对象
|
||||||
|
* @param data 数据指针
|
||||||
|
* @param len 数据长度
|
||||||
|
* @param cb 数据指针free回调函数,该参数置空时,内部会拷贝数据
|
||||||
|
* @param user_data 数据指针free回调函数on_mk_buffer_free第一个参数
|
||||||
|
* @return buffer对象
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_buffer API_CALL mk_buffer_from_char(const char *data, size_t len, on_mk_buffer_free cb, void *user_data);
|
||||||
|
API_EXPORT mk_buffer API_CALL mk_buffer_ref(mk_buffer buffer);
|
||||||
|
API_EXPORT void API_CALL mk_buffer_unref(mk_buffer buffer);
|
||||||
|
API_EXPORT const char* API_CALL mk_buffer_get_data(mk_buffer buffer);
|
||||||
|
API_EXPORT size_t API_CALL mk_buffer_get_size(mk_buffer buffer);
|
||||||
|
|
||||||
///////////////////////////////////////////SockInfo/////////////////////////////////////////////
|
///////////////////////////////////////////SockInfo/////////////////////////////////////////////
|
||||||
//SockInfo对象的C映射
|
//SockInfo对象的C映射
|
||||||
typedef void* mk_sock_info;
|
typedef void* mk_sock_info;
|
||||||
@ -47,15 +66,27 @@ API_EXPORT uint16_t API_CALL mk_sock_info_local_port(const mk_sock_info ctx);
|
|||||||
///////////////////////////////////////////TcpSession/////////////////////////////////////////////
|
///////////////////////////////////////////TcpSession/////////////////////////////////////////////
|
||||||
//TcpSession对象的C映射
|
//TcpSession对象的C映射
|
||||||
typedef void* mk_tcp_session;
|
typedef void* mk_tcp_session;
|
||||||
|
typedef void* mk_tcp_session_ref;
|
||||||
|
|
||||||
//获取基类指针以便获取其网络相关信息
|
//获取基类指针以便获取其网络相关信息
|
||||||
API_EXPORT mk_sock_info API_CALL mk_tcp_session_get_sock_info(const mk_tcp_session ctx);
|
API_EXPORT mk_sock_info API_CALL mk_tcp_session_get_sock_info(const mk_tcp_session ctx);
|
||||||
|
|
||||||
//TcpSession::safeShutdown()
|
//TcpSession::safeShutdown()
|
||||||
API_EXPORT void API_CALL mk_tcp_session_shutdown(const mk_tcp_session ctx,int err,const char *err_msg);
|
API_EXPORT void API_CALL mk_tcp_session_shutdown(const mk_tcp_session ctx,int err,const char *err_msg);
|
||||||
//TcpSession::send()
|
//TcpSession::send()
|
||||||
API_EXPORT void API_CALL mk_tcp_session_send(const mk_tcp_session ctx,const char *data,size_t len);
|
API_EXPORT void API_CALL mk_tcp_session_send(const mk_tcp_session ctx, const char *data, size_t len);
|
||||||
|
API_EXPORT void API_CALL mk_tcp_session_send_buffer(const mk_tcp_session ctx, mk_buffer buffer);
|
||||||
|
|
||||||
//切换到该对象所在线程后再TcpSession::send()
|
//切换到该对象所在线程后再TcpSession::send()
|
||||||
API_EXPORT void API_CALL mk_tcp_session_send_safe(const mk_tcp_session ctx,const char *data,size_t len);
|
API_EXPORT void API_CALL mk_tcp_session_send_safe(const mk_tcp_session ctx, const char *data, size_t len);
|
||||||
|
API_EXPORT void API_CALL mk_tcp_session_send_buffer_safe(const mk_tcp_session ctx, mk_buffer buffer);
|
||||||
|
|
||||||
|
//创建mk_tcp_session的弱引用
|
||||||
|
API_EXPORT mk_tcp_session_ref API_CALL mk_tcp_session_ref_from(const mk_tcp_session ctx);
|
||||||
|
//删除mk_tcp_session的弱引用
|
||||||
|
API_EXPORT void mk_tcp_session_ref_release(const mk_tcp_session_ref ref);
|
||||||
|
//根据弱引用获取mk_tcp_session,如果mk_tcp_session已经销毁,那么返回NULL
|
||||||
|
API_EXPORT mk_tcp_session mk_tcp_session_from_ref(const mk_tcp_session_ref ref);
|
||||||
|
|
||||||
///////////////////////////////////////////自定义tcp服务/////////////////////////////////////////////
|
///////////////////////////////////////////自定义tcp服务/////////////////////////////////////////////
|
||||||
|
|
||||||
@ -71,10 +102,9 @@ typedef struct {
|
|||||||
* 收到客户端发过来的数据
|
* 收到客户端发过来的数据
|
||||||
* @param server_port 服务器端口号
|
* @param server_port 服务器端口号
|
||||||
* @param session 会话处理对象
|
* @param session 会话处理对象
|
||||||
* @param data 数据指针
|
* @param buffer 数据
|
||||||
* @param len 数据长度
|
|
||||||
*/
|
*/
|
||||||
void (API_CALL *on_mk_tcp_session_data)(uint16_t server_port,mk_tcp_session session,const char *data,size_t len);
|
void (API_CALL *on_mk_tcp_session_data)(uint16_t server_port,mk_tcp_session session, mk_buffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每隔2秒的定时器,用于管理超时等任务
|
* 每隔2秒的定时器,用于管理超时等任务
|
||||||
@ -161,10 +191,9 @@ typedef struct {
|
|||||||
/**
|
/**
|
||||||
* 收到tcp服务器发来的数据
|
* 收到tcp服务器发来的数据
|
||||||
* @param client tcp客户端
|
* @param client tcp客户端
|
||||||
* @param data 数据指针
|
* @param buffer 数据
|
||||||
* @param len 数据长度
|
|
||||||
*/
|
*/
|
||||||
void (API_CALL *on_mk_tcp_client_data)(mk_tcp_client client,const char *data,size_t len);
|
void (API_CALL *on_mk_tcp_client_data)(mk_tcp_client client, mk_buffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 每隔2秒的定时器,用于管理超时等任务
|
* 每隔2秒的定时器,用于管理超时等任务
|
||||||
@ -205,6 +234,7 @@ API_EXPORT void API_CALL mk_tcp_client_connect(mk_tcp_client ctx, const char *ho
|
|||||||
* @param len 数据长度,等于0时,内部通过strlen获取
|
* @param len 数据长度,等于0时,内部通过strlen获取
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_tcp_client_send(mk_tcp_client ctx, const char *data, int len);
|
API_EXPORT void API_CALL mk_tcp_client_send(mk_tcp_client ctx, const char *data, int len);
|
||||||
|
API_EXPORT void API_CALL mk_tcp_client_send_buffer(mk_tcp_client ctx, mk_buffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换到本对象的网络线程后再发送数据
|
* 切换到本对象的网络线程后再发送数据
|
||||||
@ -213,6 +243,7 @@ API_EXPORT void API_CALL mk_tcp_client_send(mk_tcp_client ctx, const char *data,
|
|||||||
* @param len 数据长度,等于0时,内部通过strlen获取
|
* @param len 数据长度,等于0时,内部通过strlen获取
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_tcp_client_send_safe(mk_tcp_client ctx, const char *data, int len);
|
API_EXPORT void API_CALL mk_tcp_client_send_safe(mk_tcp_client ctx, const char *data, int len);
|
||||||
|
API_EXPORT void API_CALL mk_tcp_client_send_buffer_safe(mk_tcp_client ctx, mk_buffer buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端附着用户数据
|
* 客户端附着用户数据
|
||||||
|
@ -52,6 +52,31 @@ API_EXPORT mk_thread API_CALL mk_thread_from_pool();
|
|||||||
*/
|
*/
|
||||||
API_EXPORT mk_thread API_CALL mk_thread_from_pool_work();
|
API_EXPORT mk_thread API_CALL mk_thread_from_pool_work();
|
||||||
|
|
||||||
|
typedef void* mk_thread_pool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建线程池
|
||||||
|
* @param name 线程池名称,方便调试
|
||||||
|
* @param n_thread 线程个数,0时为cpu个数
|
||||||
|
* @param priority 线程优先级,分为PRIORITY_LOWEST = 0,PRIORITY_LOW, PRIORITY_NORMAL, PRIORITY_HIGH, PRIORITY_HIGHEST
|
||||||
|
* @return 线程池
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_thread_pool API_CALL mk_thread_pool_create(const char *name, size_t n_thread, int priority);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁线程池
|
||||||
|
* @param pool 线程池
|
||||||
|
* @return 0:成功
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_thread_pool_release(mk_thread_pool pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从线程池获取一个线程
|
||||||
|
* @param pool 线程池
|
||||||
|
* @return 线程
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_thread API_CALL mk_thread_from_thread_pool(mk_thread_pool pool);
|
||||||
|
|
||||||
///////////////////////////////////////////线程切换/////////////////////////////////////////////
|
///////////////////////////////////////////线程切换/////////////////////////////////////////////
|
||||||
typedef void (API_CALL *on_mk_async)(void *user_data);
|
typedef void (API_CALL *on_mk_async)(void *user_data);
|
||||||
|
|
||||||
@ -61,7 +86,16 @@ typedef void (API_CALL *on_mk_async)(void *user_data);
|
|||||||
* @param cb 回调函数
|
* @param cb 回调函数
|
||||||
* @param user_data 用户数据指针
|
* @param user_data 用户数据指针
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_async_do(mk_thread ctx,on_mk_async cb, void *user_data);
|
API_EXPORT void API_CALL mk_async_do(mk_thread ctx, on_mk_async cb, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换到事件线程并延时执行
|
||||||
|
* @param ctx 事件线程
|
||||||
|
* @param ms 延时时间,单位毫秒
|
||||||
|
* @param cb 回调函数
|
||||||
|
* @param user_data 用户数据指针
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_async_do_delay(mk_thread ctx, size_t ms, on_mk_async cb, void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切换到事件线程并同步执行
|
* 切换到事件线程并同步执行
|
||||||
@ -69,7 +103,7 @@ API_EXPORT void API_CALL mk_async_do(mk_thread ctx,on_mk_async cb, void *user_da
|
|||||||
* @param cb 回调函数
|
* @param cb 回调函数
|
||||||
* @param user_data 用户数据指针
|
* @param user_data 用户数据指针
|
||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_sync_do(mk_thread ctx,on_mk_async cb, void *user_data);
|
API_EXPORT void API_CALL mk_sync_do(mk_thread ctx, on_mk_async cb, void *user_data);
|
||||||
|
|
||||||
///////////////////////////////////////////定时器/////////////////////////////////////////////
|
///////////////////////////////////////////定时器/////////////////////////////////////////////
|
||||||
typedef void* mk_timer;
|
typedef void* mk_timer;
|
||||||
@ -88,7 +122,7 @@ typedef uint64_t (API_CALL *on_mk_timer)(void *user_data);
|
|||||||
* @param user_data 用户数据指针
|
* @param user_data 用户数据指针
|
||||||
* @return 定时器对象
|
* @return 定时器对象
|
||||||
*/
|
*/
|
||||||
API_EXPORT mk_timer API_CALL mk_timer_create(mk_thread ctx,uint64_t delay_ms, on_mk_timer cb, void *user_data);
|
API_EXPORT mk_timer API_CALL mk_timer_create(mk_thread ctx, uint64_t delay_ms, on_mk_timer cb, void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 销毁和取消定时器
|
* 销毁和取消定时器
|
||||||
@ -96,6 +130,31 @@ API_EXPORT mk_timer API_CALL mk_timer_create(mk_thread ctx,uint64_t delay_ms, on
|
|||||||
*/
|
*/
|
||||||
API_EXPORT void API_CALL mk_timer_release(mk_timer ctx);
|
API_EXPORT void API_CALL mk_timer_release(mk_timer ctx);
|
||||||
|
|
||||||
|
///////////////////////////////////////////信号量/////////////////////////////////////////////
|
||||||
|
|
||||||
|
typedef void* mk_sem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建信号量
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_sem API_CALL mk_sem_create();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁信号量
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_sem_release(mk_sem sem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信号量加n
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_sem_post(mk_sem sem, size_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 信号量减1
|
||||||
|
* @param sem
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_sem_wait(mk_sem sem);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
135
api/include/mk_track.h
Normal file
135
api/include/mk_track.h
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_MK_TRACK_H
|
||||||
|
#define ZLMEDIAKIT_MK_TRACK_H
|
||||||
|
|
||||||
|
#include "mk_common.h"
|
||||||
|
#include "mk_frame.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//音视频轨道
|
||||||
|
typedef void* mk_track;
|
||||||
|
//输出frame回调
|
||||||
|
typedef void(API_CALL *on_mk_frame_out)(void *user_data, mk_frame frame);
|
||||||
|
|
||||||
|
//track创建参数
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int fps;
|
||||||
|
} video;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
int channels;
|
||||||
|
int sample_rate;
|
||||||
|
} audio;
|
||||||
|
} codec_args;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建track对象引用
|
||||||
|
* @param codec_id 请参考MKCodecXXX 常量定义
|
||||||
|
* @param args 视频或音频参数
|
||||||
|
* @return track对象引用
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_track API_CALL mk_track_create(int codec_id, codec_args *args);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 减引用track对象
|
||||||
|
* @param track track对象
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_track_unref(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 引用track对象
|
||||||
|
* @param track track对象
|
||||||
|
* @return 新的track引用对象
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_track API_CALL mk_track_ref(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取track 编码codec类型,请参考MKCodecXXX定义
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_codec_id(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取编码codec名称
|
||||||
|
*/
|
||||||
|
API_EXPORT const char* API_CALL mk_track_codec_name(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取比特率信息
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_bit_rate(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听frame输出事件
|
||||||
|
* @param track track对象
|
||||||
|
* @param cb frame输出回调
|
||||||
|
* @param user_data frame输出回调用户指针参数
|
||||||
|
*/
|
||||||
|
API_EXPORT void *API_CALL mk_track_add_delegate(mk_track track, on_mk_frame_out cb, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消frame输出事件监听
|
||||||
|
* @param track track对象
|
||||||
|
* @param tag mk_track_add_delegate返回值
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_track_del_delegate(mk_track track, void *tag);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 输入frame到track,通常你不需要调用此api
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_track_input_frame(mk_track track, mk_frame frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* track是否为视频
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_is_video(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取视频宽度
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_video_width(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取视频高度
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_video_height(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取视频帧率
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_video_fps(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取音频采样率
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_audio_sample_rate(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取音频通道数
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_audio_channel(mk_track track);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取音频位数,一般为16bit
|
||||||
|
*/
|
||||||
|
API_EXPORT int API_CALL mk_track_audio_sample_bit(mk_track track);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_MK_TRACK_H
|
154
api/include/mk_transcode.h
Normal file
154
api/include/mk_transcode.h
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZLMEDIAKIT_MK_TRANSCODE_H
|
||||||
|
#define ZLMEDIAKIT_MK_TRANSCODE_H
|
||||||
|
|
||||||
|
#include "mk_common.h"
|
||||||
|
#include "mk_track.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//解码器对象
|
||||||
|
typedef void *mk_decoder;
|
||||||
|
//解码后的frame
|
||||||
|
typedef void *mk_frame_pix;
|
||||||
|
//SwsContext的包装
|
||||||
|
typedef void *mk_swscale;
|
||||||
|
//FFmpeg原始解码帧对象
|
||||||
|
typedef struct AVFrame AVFrame;
|
||||||
|
//FFmpeg编解码器对象
|
||||||
|
typedef struct AVCodecContext AVCodecContext;
|
||||||
|
//解码输出回调
|
||||||
|
typedef void(API_CALL *on_mk_decode)(void *user_data, mk_frame_pix frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建解码器
|
||||||
|
* @param track track对象
|
||||||
|
* @param thread_num 解码线程数,0时为自动
|
||||||
|
* @return 返回解码器对象,NULL代表失败
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_decoder API_CALL mk_decoder_create(mk_track track, int thread_num);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 销毁解码器
|
||||||
|
* @param ctx 解码器对象
|
||||||
|
* @param flush_frame 是否等待所有帧解码成功
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_decoder_release(mk_decoder ctx, int flush_frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解码音视频帧
|
||||||
|
* @param ctx 解码器
|
||||||
|
* @param frame 帧对象
|
||||||
|
* @param async 是否异步解码
|
||||||
|
* @param enable_merge 是否合并帧解码,有些情况下,需要把时间戳相同的slice合并输入到解码器才能解码
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_decoder_decode(mk_decoder ctx, mk_frame frame, int async, int enable_merge);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置异步解码最大帧缓存积压数限制
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_decoder_set_max_async_frame_size(mk_decoder ctx, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置解码输出回调
|
||||||
|
* @param ctx 解码器
|
||||||
|
* @param cb 回调函数
|
||||||
|
* @param user_data 回调函数用户指针参数
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_decoder_set_cb(mk_decoder ctx, on_mk_decode cb, void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取FFmpeg原始AVCodecContext对象
|
||||||
|
* @param ctx 解码器
|
||||||
|
*/
|
||||||
|
API_EXPORT const AVCodecContext* API_CALL mk_decoder_get_context(mk_decoder ctx);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建解码帧mk_frame_pix新引用
|
||||||
|
* @param frame 原始引用
|
||||||
|
* @return 新引用
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_frame_pix API_CALL mk_frame_pix_ref(mk_frame_pix frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解码帧mk_frame_pix减引用
|
||||||
|
* @param frame 原始引用
|
||||||
|
*/
|
||||||
|
API_EXPORT void API_CALL mk_frame_pix_unref(mk_frame_pix frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从FFmpeg AVFrame转换为mk_frame_pix
|
||||||
|
* @param frame FFmpeg AVFrame
|
||||||
|
* @return mk_frame_pix对象
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_frame_pix API_CALL mk_frame_pix_from_av_frame(AVFrame *frame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取FFmpeg AVFrame对象
|
||||||
|
* @param frame 解码帧mk_frame_pix
|
||||||
|
* @return FFmpeg AVFrame对象
|
||||||
|
*/
|
||||||
|
API_EXPORT AVFrame* API_CALL mk_frame_pix_get_av_frame(mk_frame_pix frame);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建ffmpeg SwsContext wrapper实例
|
||||||
|
* @param output AVPixelFormat类型,AV_PIX_FMT_BGR24==3
|
||||||
|
* @param width 目标宽度,置0时,则与输入时一致
|
||||||
|
* @param height 目标高度,置0时,则与输入时一致
|
||||||
|
* @return SwsContext wrapper 实例
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_swscale mk_swscale_create(int output, int width, int height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 释放ffmpeg SwsContext wrapper实例
|
||||||
|
* @param ctx SwsContext wrapper实例
|
||||||
|
*/
|
||||||
|
API_EXPORT void mk_swscale_release(mk_swscale ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用SwsContext转换pix format
|
||||||
|
* @param ctx SwsContext wrapper实例
|
||||||
|
* @param frame pix frame
|
||||||
|
* @param out 转换后存放的数据指针,用户需要确保提前申请并大小足够
|
||||||
|
* @return sws_scale()返回值:the height of the output slice
|
||||||
|
*/
|
||||||
|
API_EXPORT int mk_swscale_input_frame(mk_swscale ctx, mk_frame_pix frame, uint8_t *out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用SwsContext转换pix format
|
||||||
|
* @param ctx SwsContext wrapper实例
|
||||||
|
* @param frame pix frame
|
||||||
|
* @return 新的pix frame对象,需要使用mk_frame_pix_unref销毁
|
||||||
|
*/
|
||||||
|
API_EXPORT mk_frame_pix mk_swscale_input_frame2(mk_swscale ctx, mk_frame_pix frame);
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
API_EXPORT uint8_t** API_CALL mk_get_av_frame_data(AVFrame *frame);
|
||||||
|
API_EXPORT int* API_CALL mk_get_av_frame_line_size(AVFrame *frame);
|
||||||
|
API_EXPORT int64_t API_CALL mk_get_av_frame_dts(AVFrame *frame);
|
||||||
|
API_EXPORT int64_t API_CALL mk_get_av_frame_pts(AVFrame *frame);
|
||||||
|
API_EXPORT int API_CALL mk_get_av_frame_width(AVFrame *frame);
|
||||||
|
API_EXPORT int API_CALL mk_get_av_frame_height(AVFrame *frame);
|
||||||
|
API_EXPORT int API_CALL mk_get_av_frame_format(AVFrame *frame);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif //ZLMEDIAKIT_MK_TRANSCODE_H
|
@ -7,6 +7,7 @@
|
|||||||
* LICENSE file in the root of the source tree. All contributing project authors
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
* may be found in the AUTHORS file in the root of the source tree.
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef ENABLE_WEBRTC
|
#ifdef ENABLE_WEBRTC
|
||||||
#ifndef MK_WEBRTC_API_H
|
#ifndef MK_WEBRTC_API_H
|
||||||
#define MK_WEBRTC_API_H
|
#define MK_WEBRTC_API_H
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "Util/logger.h"
|
#include "Util/logger.h"
|
||||||
#include "Util/SSLBox.h"
|
#include "Util/SSLBox.h"
|
||||||
#include "Network/TcpServer.h"
|
#include "Network/TcpServer.h"
|
||||||
|
#include "Network/UdpServer.h"
|
||||||
#include "Thread/WorkThreadPool.h"
|
#include "Thread/WorkThreadPool.h"
|
||||||
|
|
||||||
#include "Rtsp/RtspSession.h"
|
#include "Rtsp/RtspSession.h"
|
||||||
|
176
api/source/mk_frame.cpp
Normal file
176
api/source/mk_frame.cpp
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mk_frame.h"
|
||||||
|
#include "Extension/Frame.h"
|
||||||
|
#include "Extension/H264.h"
|
||||||
|
#include "Extension/H265.h"
|
||||||
|
#include "Extension/AAC.h"
|
||||||
|
|
||||||
|
using namespace mediakit;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#define XX(name, type, value, str, mpeg_id) const int MK##name = value;
|
||||||
|
CODEC_MAP(XX)
|
||||||
|
#undef XX
|
||||||
|
}
|
||||||
|
|
||||||
|
class FrameFromPtrForC : public FrameFromPtr {
|
||||||
|
public:
|
||||||
|
using Ptr = std::shared_ptr<FrameFromPtrForC>;
|
||||||
|
|
||||||
|
template<typename ...ARGS>
|
||||||
|
FrameFromPtrForC(bool cache_able, uint32_t flags, on_mk_frame_data_release cb, void *user_data, ARGS &&...args) : FrameFromPtr(
|
||||||
|
std::forward<ARGS>(args)...) {
|
||||||
|
_flags = flags;
|
||||||
|
_cb = cb;
|
||||||
|
_user_data = user_data;
|
||||||
|
_cache_able = cache_able;
|
||||||
|
}
|
||||||
|
|
||||||
|
~FrameFromPtrForC() override {
|
||||||
|
if (_cb) {
|
||||||
|
_cb(_user_data, _ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cacheAble() const override {
|
||||||
|
return _cache_able;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyFrame() const override {
|
||||||
|
return _flags & MK_FRAME_FLAG_IS_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool configFrame() const override {
|
||||||
|
return _flags & MK_FRAME_FLAG_IS_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
//默认返回false
|
||||||
|
bool dropAble() const override {
|
||||||
|
return _flags & MK_FRAME_FLAG_DROP_ABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
//默认返回true
|
||||||
|
bool decodeAble() const override {
|
||||||
|
return !(_flags & MK_FRAME_FLAG_NOT_DECODE_ABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t _flags;
|
||||||
|
on_mk_frame_data_release _cb;
|
||||||
|
void *_user_data;
|
||||||
|
bool _cache_able;
|
||||||
|
};
|
||||||
|
|
||||||
|
static mk_frame mk_frame_create_complex(int codec_id, uint32_t dts, uint32_t pts, uint32_t frame_flags, size_t prefix_size,
|
||||||
|
char *data, size_t size, on_mk_frame_data_release cb, void *user_data) {
|
||||||
|
switch (codec_id) {
|
||||||
|
case CodecH264:
|
||||||
|
return new Frame::Ptr(new H264FrameHelper<FrameFromPtrForC>(cb, frame_flags, cb, user_data, (CodecId) codec_id,
|
||||||
|
data, size, dts, pts, prefix_size));
|
||||||
|
case CodecH265:
|
||||||
|
return new Frame::Ptr(new H265FrameHelper<FrameFromPtrForC>(cb, frame_flags, cb, user_data, (CodecId) codec_id,
|
||||||
|
data, size, dts, pts, prefix_size));
|
||||||
|
default:
|
||||||
|
return new Frame::Ptr(new FrameFromPtrForC(cb, frame_flags, cb, user_data, (CodecId) codec_id, data,
|
||||||
|
size, dts, pts, prefix_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_frame API_CALL mk_frame_create(int codec_id, uint32_t dts, uint32_t pts, const char *data, size_t size,
|
||||||
|
on_mk_frame_data_release cb, void *user_data) {
|
||||||
|
|
||||||
|
switch (codec_id) {
|
||||||
|
case CodecH264:
|
||||||
|
case CodecH265:
|
||||||
|
return mk_frame_create_complex(codec_id, dts, pts, 0, prefixSize(data, size), (char *)data, size, cb, user_data);
|
||||||
|
|
||||||
|
case CodecAAC: {
|
||||||
|
int prefix = 0;
|
||||||
|
if ((((uint8_t *) data)[0] == 0xFF && (((uint8_t *) data)[1] & 0xF0) == 0xF0) && size > ADTS_HEADER_LEN) {
|
||||||
|
prefix = ADTS_HEADER_LEN;
|
||||||
|
}
|
||||||
|
return mk_frame_create_complex(codec_id, dts, pts, 0, prefix, (char *)data, size, cb, user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return mk_frame_create_complex(codec_id, dts, pts, 0, 0, (char *)data, size, cb, user_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_frame_unref(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
delete (Frame::Ptr *) frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_frame API_CALL mk_frame_ref(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return new Frame::Ptr(Frame::getCacheAbleFrame(*((Frame::Ptr *) frame)));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_frame_codec_id(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->getCodecId();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT const char *API_CALL mk_frame_codec_name(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->getCodecName();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_frame_is_video(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->getTrackType() == TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT const char *API_CALL mk_frame_get_data(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT size_t API_CALL mk_frame_get_data_size(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT size_t API_CALL mk_frame_get_data_prefix_size(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->prefixSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT uint32_t API_CALL mk_frame_get_dts(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->dts();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT uint32_t API_CALL mk_frame_get_pts(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*((Frame::Ptr *) frame))->pts();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT uint32_t API_CALL mk_frame_get_flags(mk_frame frame) {
|
||||||
|
assert(frame);
|
||||||
|
auto &ref = *((Frame::Ptr *) frame);
|
||||||
|
uint32_t ret = 0;
|
||||||
|
if (ref->keyFrame()) {
|
||||||
|
ret &= MK_FRAME_FLAG_IS_KEY;
|
||||||
|
}
|
||||||
|
if (ref->configFrame()) {
|
||||||
|
ret &= MK_FRAME_FLAG_IS_CONFIG;
|
||||||
|
}
|
||||||
|
if (ref->dropAble()) {
|
||||||
|
ret &= MK_FRAME_FLAG_DROP_ABLE;
|
||||||
|
}
|
||||||
|
if (!ref->decodeAble()) {
|
||||||
|
ret &= MK_FRAME_FLAG_NOT_DECODE_ABLE;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
@ -178,7 +178,7 @@ API_EXPORT void API_CALL mk_media_release(mk_media ctx) {
|
|||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_media_init_video(mk_media ctx, int codec_id, int width, int height, float fps){
|
API_EXPORT int API_CALL mk_media_init_video(mk_media ctx, int codec_id, int width, int height, float fps, int bit_rate){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
VideoInfo info;
|
VideoInfo info;
|
||||||
@ -186,6 +186,8 @@ API_EXPORT int API_CALL mk_media_init_video(mk_media ctx, int codec_id, int widt
|
|||||||
info.iFrameRate = fps;
|
info.iFrameRate = fps;
|
||||||
info.iWidth = width;
|
info.iWidth = width;
|
||||||
info.iHeight = height;
|
info.iHeight = height;
|
||||||
|
info.iBitRate = bit_rate;
|
||||||
|
(*obj)->getChannel()->initVideo(info);
|
||||||
return (*obj)->getChannel()->initVideo(info);
|
return (*obj)->getChannel()->initVideo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,12 +202,24 @@ API_EXPORT int API_CALL mk_media_init_audio(mk_media ctx, int codec_id, int samp
|
|||||||
return (*obj)->getChannel()->initAudio(info);
|
return (*obj)->getChannel()->initAudio(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_media_init_track(mk_media ctx, mk_track track){
|
||||||
|
assert(ctx && track);
|
||||||
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
|
(*obj)->getChannel()->addTrack(*((Track::Ptr *) track));
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx){
|
API_EXPORT void API_CALL mk_media_init_complete(mk_media ctx){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
(*obj)->getChannel()->addTrackCompleted();
|
(*obj)->getChannel()->addTrackCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_media_input_frame(mk_media ctx, mk_frame frame){
|
||||||
|
assert(ctx && frame);
|
||||||
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
|
return (*obj)->getChannel()->inputFrame(*((Frame::Ptr *) frame));
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_media_input_h264(mk_media ctx, const void *data, int len, uint32_t dts, uint32_t pts) {
|
API_EXPORT int API_CALL mk_media_input_h264(mk_media ctx, const void *data, int len, uint32_t dts, uint32_t pts) {
|
||||||
assert(ctx && data && len > 0);
|
assert(ctx && data && len > 0);
|
||||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
@ -218,6 +232,12 @@ API_EXPORT int API_CALL mk_media_input_h265(mk_media ctx, const void *data, int
|
|||||||
return (*obj)->getChannel()->inputH265((const char *) data, len, dts, pts);
|
return (*obj)->getChannel()->inputH265((const char *) data, len, dts, pts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_media_input_yuv(mk_media ctx, const char *yuv[3], int linesize[3], uint32_t cts) {
|
||||||
|
assert(ctx && yuv && linesize);
|
||||||
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
|
(*obj)->getChannel()->inputYUV((char **) yuv, linesize, cts);
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_media_input_aac(mk_media ctx, const void *data, int len, uint32_t dts, void *adts) {
|
API_EXPORT int API_CALL mk_media_input_aac(mk_media ctx, const void *data, int len, uint32_t dts, void *adts) {
|
||||||
assert(ctx && data && len > 0 && adts);
|
assert(ctx && data && len > 0 && adts);
|
||||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||||
|
@ -47,51 +47,34 @@ public:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void unset(){
|
void unset() {
|
||||||
|
for (auto &track : _player->getTracks(false)) {
|
||||||
|
track->clear();
|
||||||
|
}
|
||||||
lock_guard<recursive_mutex> lck(_mtx);
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
_on_play = nullptr;
|
_on_play = nullptr;
|
||||||
_on_shutdown = nullptr;
|
_on_shutdown = nullptr;
|
||||||
_on_data = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onEvent(bool is_shutdown, const SockException &ex){
|
void onEvent(bool is_shutdown, const SockException &ex){
|
||||||
lock_guard<recursive_mutex> lck(_mtx);
|
lock_guard<recursive_mutex> lck(_mtx);
|
||||||
if(is_shutdown){
|
if (is_shutdown) {
|
||||||
//播放中断
|
//播放中断
|
||||||
if(_on_shutdown){
|
if (_on_shutdown) {
|
||||||
_on_shutdown(_on_shutdown_data,ex.getErrCode(),ex.what());
|
_on_shutdown(_on_shutdown_data, ex.getErrCode(), ex.what(), nullptr, 0);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//播放结果
|
//播放结果
|
||||||
if(_on_play){
|
if (_on_play) {
|
||||||
_on_play(_on_play_data,ex.getErrCode(),ex.what());
|
auto cpp_tracks = _player->getTracks(false);
|
||||||
}
|
mk_track tracks[TrackMax] = {nullptr};
|
||||||
|
int track_count = 0;
|
||||||
if(ex){
|
for (auto &track : cpp_tracks) {
|
||||||
//播放失败
|
tracks[track_count++] = (mk_track) &track;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//播放成功,添加事件回调
|
|
||||||
weak_ptr<MediaPlayerForC> weak_self = shared_from_this();
|
|
||||||
auto delegate = std::make_shared<FrameWriterInterfaceHelper>([weak_self](const Frame::Ptr &frame) {
|
|
||||||
if (auto strong_self = weak_self.lock()) {
|
|
||||||
strong_self->onData(frame);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
_on_play(_on_play_data, ex.getErrCode(), ex.what(), tracks, track_count);
|
||||||
});
|
|
||||||
for (auto &track : _player->getTracks(false)) {
|
|
||||||
track->addDelegate(delegate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onData(const Frame::Ptr &frame){
|
|
||||||
lock_guard<recursive_mutex> lck(_mtx);
|
|
||||||
if(_on_data){
|
|
||||||
_on_data(_on_data_data,frame->getTrackType(),frame->getCodecId(),frame->data(),frame->size(),frame->dts(),frame->pts());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,12 +89,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setOnData(on_mk_play_data cb, void *user_data) {
|
|
||||||
lock_guard<recursive_mutex> lck(_mtx);
|
|
||||||
_on_data_data = user_data;
|
|
||||||
_on_data = cb;
|
|
||||||
}
|
|
||||||
|
|
||||||
MediaPlayer::Ptr& getPlayer(){
|
MediaPlayer::Ptr& getPlayer(){
|
||||||
return _player;
|
return _player;
|
||||||
}
|
}
|
||||||
@ -119,12 +96,10 @@ private:
|
|||||||
MediaPlayer::Ptr _player;
|
MediaPlayer::Ptr _player;
|
||||||
recursive_mutex _mtx;
|
recursive_mutex _mtx;
|
||||||
on_mk_play_event _on_play = nullptr;
|
on_mk_play_event _on_play = nullptr;
|
||||||
on_mk_play_data _on_data = nullptr;
|
|
||||||
on_mk_play_event _on_shutdown = nullptr;
|
on_mk_play_event _on_shutdown = nullptr;
|
||||||
|
|
||||||
void *_on_play_data = nullptr;
|
void *_on_play_data = nullptr;
|
||||||
void *_on_shutdown_data = nullptr;
|
void *_on_shutdown_data = nullptr;
|
||||||
void *_on_data_data = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
API_EXPORT mk_player API_CALL mk_player_create() {
|
API_EXPORT mk_player API_CALL mk_player_create() {
|
||||||
@ -214,90 +189,6 @@ API_EXPORT void API_CALL mk_player_set_on_shutdown(mk_player ctx, on_mk_play_eve
|
|||||||
mk_player_set_on_event(ctx,cb,user_data,1);
|
mk_player_set_on_event(ctx,cb,user_data,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_player_set_on_data(mk_player ctx, on_mk_play_data cb, void *user_data) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
obj.setOnData(cb,user_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_video_codec_id(mk_player ctx){
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
|
||||||
return track ? track->getCodecId() : CodecInvalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_video_codec_id_vendor_head(mk_player ctx, char *vendor, char *head, int *head_len) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *) ctx);
|
|
||||||
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
|
||||||
int codecId = track ? track->getCodecId() : CodecInvalid;
|
|
||||||
if (codecId == CodecH264) {
|
|
||||||
auto h264Track = dynamic_pointer_cast<H264Track>(obj->getTrack(TrackVideo));
|
|
||||||
auto pps = h264Track->getPps();
|
|
||||||
auto ppsLen = pps.size();
|
|
||||||
if (ppsLen >= (4 + 16)) {
|
|
||||||
std::string temVendor = std::string(pps.c_str() + 4, 16);
|
|
||||||
memcpy(vendor, temVendor.c_str(), temVendor.length());
|
|
||||||
if (ppsLen > (4 + 16)) {
|
|
||||||
std::string temHead = std::string(pps.c_str() + 20, ppsLen - 20);
|
|
||||||
memcpy(head, temHead.c_str(), temHead.length());
|
|
||||||
*head_len = temHead.length();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return codecId;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_video_width(mk_player ctx) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
|
||||||
return track ? track->getVideoWidth() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_video_height(mk_player ctx) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
|
||||||
return track ? track->getVideoHeight() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT float API_CALL mk_player_video_fps(mk_player ctx) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<VideoTrack>(obj->getTrack(TrackVideo));
|
|
||||||
return track ? track->getVideoFps() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_codec_id(mk_player ctx){
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<AudioTrack>(obj->getTrack(TrackAudio));
|
|
||||||
return track ? track->getCodecId() : CodecInvalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_samplerate(mk_player ctx) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<AudioTrack>(obj->getTrack(TrackAudio));
|
|
||||||
return track ? track->getAudioSampleRate() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_bit(mk_player ctx) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<AudioTrack>(obj->getTrack(TrackAudio));
|
|
||||||
return track ? track->getAudioSampleBit() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT int API_CALL mk_player_audio_channel(mk_player ctx) {
|
|
||||||
assert(ctx);
|
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
|
||||||
auto track = dynamic_pointer_cast<AudioTrack>(obj->getTrack(TrackAudio));
|
|
||||||
return track ? track->getAudioChannel() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
API_EXPORT float API_CALL mk_player_duration(mk_player ctx) {
|
API_EXPORT float API_CALL mk_player_duration(mk_player ctx) {
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
||||||
|
@ -13,10 +13,76 @@
|
|||||||
#include "mk_tcp_private.h"
|
#include "mk_tcp_private.h"
|
||||||
#include "Http/WebSocketClient.h"
|
#include "Http/WebSocketClient.h"
|
||||||
#include "Http/WebSocketSession.h"
|
#include "Http/WebSocketSession.h"
|
||||||
|
#include "Network/Buffer.h"
|
||||||
|
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
using namespace mediakit;
|
using namespace mediakit;
|
||||||
|
|
||||||
|
class BufferForC : public Buffer {
|
||||||
|
public:
|
||||||
|
BufferForC(const char *data, size_t len, on_mk_buffer_free cb, void *user_data) {
|
||||||
|
if (len <= 0) {
|
||||||
|
len = strlen(data);
|
||||||
|
}
|
||||||
|
if (!cb) {
|
||||||
|
auto ptr = malloc(len);
|
||||||
|
memcpy(ptr, data, len);
|
||||||
|
data = (char *) ptr;
|
||||||
|
|
||||||
|
cb = [](void *user_data, void *data) {
|
||||||
|
free(data);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
_data = (char *) data;
|
||||||
|
_size = len;
|
||||||
|
_cb = cb;
|
||||||
|
_user_data = user_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
~BufferForC() override {
|
||||||
|
_cb(_user_data, _data);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *data() const override {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const override {
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char *_data;
|
||||||
|
size_t _size;
|
||||||
|
on_mk_buffer_free _cb;
|
||||||
|
void *_user_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
API_EXPORT mk_buffer API_CALL mk_buffer_from_char(const char *data, size_t len, on_mk_buffer_free cb, void *user_data) {
|
||||||
|
assert(data);
|
||||||
|
return new Buffer::Ptr(std::make_shared<BufferForC>(data, len, cb, user_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_buffer API_CALL mk_buffer_ref(mk_buffer buffer) {
|
||||||
|
assert(buffer);
|
||||||
|
return new Buffer::Ptr(*((Buffer::Ptr *) buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_buffer_unref(mk_buffer buffer) {
|
||||||
|
assert(buffer);
|
||||||
|
delete (Buffer::Ptr *) buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT const char *API_CALL mk_buffer_get_data(mk_buffer buffer) {
|
||||||
|
assert(buffer);
|
||||||
|
return (*((Buffer::Ptr *) buffer))->data();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT size_t API_CALL mk_buffer_get_size(mk_buffer buffer) {
|
||||||
|
assert(buffer);
|
||||||
|
return (*((Buffer::Ptr *) buffer))->size();
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORT const char* API_CALL mk_sock_info_peer_ip(const mk_sock_info ctx, char *buf){
|
API_EXPORT const char* API_CALL mk_sock_info_peer_ip(const mk_sock_info ctx, char *buf){
|
||||||
assert(ctx);
|
assert(ctx);
|
||||||
SockInfo *sock = (SockInfo *)ctx;
|
SockInfo *sock = (SockInfo *)ctx;
|
||||||
@ -53,34 +119,54 @@ API_EXPORT void API_CALL mk_tcp_session_shutdown(const mk_tcp_session ctx,int er
|
|||||||
session->safeShutdown(SockException((ErrCode)err,err_msg));
|
session->safeShutdown(SockException((ErrCode)err,err_msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_tcp_session_send(const mk_tcp_session ctx,const char *data, size_t len){
|
API_EXPORT void API_CALL mk_tcp_session_send_buffer(const mk_tcp_session ctx, mk_buffer buffer) {
|
||||||
assert(ctx && data);
|
assert(ctx && buffer);
|
||||||
if(!len){
|
TcpSessionForC *session = (TcpSessionForC *) ctx;
|
||||||
len = strlen(data);
|
session->send(*((Buffer::Ptr *) buffer));
|
||||||
}
|
|
||||||
TcpSessionForC *session = (TcpSessionForC *)ctx;
|
|
||||||
session->SockSender::send(data,len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_tcp_session_send_safe(const mk_tcp_session ctx,const char *data,size_t len){
|
API_EXPORT void API_CALL mk_tcp_session_send(const mk_tcp_session ctx, const char *data, size_t len) {
|
||||||
assert(ctx && data);
|
auto buffer = mk_buffer_from_char(data, len, nullptr, nullptr);
|
||||||
if (!len) {
|
mk_tcp_session_send_buffer(ctx, buffer);
|
||||||
len = strlen(data);
|
mk_buffer_unref(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_tcp_session_send_buffer_safe(const mk_tcp_session ctx, mk_buffer buffer) {
|
||||||
|
assert(ctx && buffer);
|
||||||
try {
|
try {
|
||||||
std::weak_ptr<TcpSession> weak_session = ((TcpSessionForC *)ctx)->shared_from_this();
|
std::weak_ptr<TcpSession> weak_session = ((TcpSessionForC *) ctx)->shared_from_this();
|
||||||
std::string str = std::string(data,len);
|
auto ref = mk_buffer_ref(buffer);
|
||||||
((TcpSessionForC *)ctx)->async([weak_session,str](){
|
((TcpSessionForC *) ctx)->async([weak_session, ref]() {
|
||||||
auto session_session = weak_session.lock();
|
auto session_session = weak_session.lock();
|
||||||
if(session_session){
|
if (session_session) {
|
||||||
session_session->SockSender::send(str);
|
session_session->send(*((Buffer::Ptr *) ref));
|
||||||
}
|
}
|
||||||
|
mk_buffer_unref(ref);
|
||||||
});
|
});
|
||||||
} catch (std::exception &ex) {
|
} catch (std::exception &ex) {
|
||||||
WarnL << "can not got the strong pionter of this mk_tcp_session:" << ex.what();
|
WarnL << "can not got the strong pionter of this mk_tcp_session:" << ex.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_tcp_session_ref API_CALL mk_tcp_session_ref_from(const mk_tcp_session ctx) {
|
||||||
|
auto ref = ((TcpSessionForC *) ctx)->shared_from_this();
|
||||||
|
return new std::shared_ptr<TcpSessionForC>(std::dynamic_pointer_cast<TcpSessionForC>(ref));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void mk_tcp_session_ref_release(const mk_tcp_session_ref ref) {
|
||||||
|
delete (std::shared_ptr<TcpSessionForC> *) ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_tcp_session mk_tcp_session_from_ref(const mk_tcp_session_ref ref) {
|
||||||
|
return ((std::shared_ptr<TcpSessionForC> *) ref)->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_tcp_session_send_safe(const mk_tcp_session ctx, const char *data, size_t len) {
|
||||||
|
auto buffer = mk_buffer_from_char(data, len, nullptr, nullptr);
|
||||||
|
mk_tcp_session_send_buffer_safe(ctx, buffer);
|
||||||
|
mk_buffer_unref(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////TcpSessionForC////////////////////////////////////////////////
|
////////////////////////////////////////TcpSessionForC////////////////////////////////////////////////
|
||||||
static TcpServer::Ptr s_tcp_server[4];
|
static TcpServer::Ptr s_tcp_server[4];
|
||||||
static mk_tcp_session_events s_events_server = {0};
|
static mk_tcp_session_events s_events_server = {0};
|
||||||
@ -94,7 +180,7 @@ TcpSessionForC::TcpSessionForC(const Socket::Ptr &pSock) : TcpSession(pSock) {
|
|||||||
|
|
||||||
void TcpSessionForC::onRecv(const Buffer::Ptr &buffer) {
|
void TcpSessionForC::onRecv(const Buffer::Ptr &buffer) {
|
||||||
if (s_events_server.on_mk_tcp_session_data) {
|
if (s_events_server.on_mk_tcp_session_data) {
|
||||||
s_events_server.on_mk_tcp_session_data(_local_port,this, buffer->data(), buffer->size());
|
s_events_server.on_mk_tcp_session_data(_local_port, this, (mk_buffer)&buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,10 +255,9 @@ TcpClientForC::TcpClientForC(mk_tcp_client_events *events){
|
|||||||
_events = *events;
|
_events = *events;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TcpClientForC::onRecv(const Buffer::Ptr &pBuf) {
|
void TcpClientForC::onRecv(const Buffer::Ptr &pBuf) {
|
||||||
if(_events.on_mk_tcp_client_data){
|
if (_events.on_mk_tcp_client_data) {
|
||||||
_events.on_mk_tcp_client_data(_client,pBuf->data(),pBuf->size());
|
_events.on_mk_tcp_client_data(_client, (mk_buffer)&pBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,24 +331,36 @@ API_EXPORT void API_CALL mk_tcp_client_connect(mk_tcp_client ctx, const char *ho
|
|||||||
(*client)->startConnect(host,port);
|
(*client)->startConnect(host,port);
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_tcp_client_send(mk_tcp_client ctx, const char *data, int len){
|
API_EXPORT void API_CALL mk_tcp_client_send_buffer(mk_tcp_client ctx, mk_buffer buffer) {
|
||||||
assert(ctx && data);
|
assert(ctx && buffer);
|
||||||
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *)ctx;
|
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *) ctx;
|
||||||
(*client)->SockSender::send(data,len);
|
(*client)->send(*((Buffer::Ptr *) buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_tcp_client_send(mk_tcp_client ctx, const char *data, int len) {
|
||||||
|
auto buffer = mk_buffer_from_char(data, len, nullptr, nullptr);
|
||||||
|
mk_tcp_client_send_buffer(ctx, buffer);
|
||||||
|
mk_buffer_unref(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_tcp_client_send_buffer_safe(mk_tcp_client ctx, mk_buffer buffer) {
|
||||||
|
assert(ctx && buffer);
|
||||||
|
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *) ctx;
|
||||||
|
std::weak_ptr<TcpClient> weakClient = *client;
|
||||||
|
auto ref = mk_buffer_ref(buffer);
|
||||||
|
(*client)->async([weakClient, ref]() {
|
||||||
|
auto strongClient = weakClient.lock();
|
||||||
|
if (strongClient) {
|
||||||
|
strongClient->send(*((Buffer::Ptr *) ref));
|
||||||
|
}
|
||||||
|
mk_buffer_unref(ref);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_tcp_client_send_safe(mk_tcp_client ctx, const char *data, int len){
|
API_EXPORT void API_CALL mk_tcp_client_send_safe(mk_tcp_client ctx, const char *data, int len){
|
||||||
assert(ctx && data);
|
auto buffer = mk_buffer_from_char(data, len, nullptr, nullptr);
|
||||||
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *)ctx;
|
mk_tcp_client_send_buffer_safe(ctx, buffer);
|
||||||
std::weak_ptr<TcpClient> weakClient = *client;
|
mk_buffer_unref(buffer);
|
||||||
auto buf = BufferRaw::create();
|
|
||||||
buf->assign(data,len);
|
|
||||||
(*client)->async([weakClient,buf](){
|
|
||||||
auto strongClient = weakClient.lock();
|
|
||||||
if(strongClient){
|
|
||||||
strongClient->send(buf);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_tcp_client_set_user_data(mk_tcp_client ctx,void *user_data){
|
API_EXPORT void API_CALL mk_tcp_client_set_user_data(mk_tcp_client ctx,void *user_data){
|
||||||
|
@ -44,6 +44,15 @@ API_EXPORT void API_CALL mk_async_do(mk_thread ctx,on_mk_async cb, void *user_da
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_async_do_delay(mk_thread ctx, size_t ms, on_mk_async cb, void *user_data) {
|
||||||
|
assert(ctx && cb && ms);
|
||||||
|
EventPoller *poller = (EventPoller *) ctx;
|
||||||
|
poller->doDelayTask(ms, [cb, user_data]() {
|
||||||
|
cb(user_data);
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
API_EXPORT void API_CALL mk_sync_do(mk_thread ctx,on_mk_async cb, void *user_data){
|
API_EXPORT void API_CALL mk_sync_do(mk_thread ctx,on_mk_async cb, void *user_data){
|
||||||
assert(ctx && cb);
|
assert(ctx && cb);
|
||||||
EventPoller *poller = (EventPoller *)ctx;
|
EventPoller *poller = (EventPoller *)ctx;
|
||||||
@ -107,4 +116,52 @@ API_EXPORT void API_CALL mk_timer_release(mk_timer ctx){
|
|||||||
TimerForC::Ptr *obj = (TimerForC::Ptr *)ctx;
|
TimerForC::Ptr *obj = (TimerForC::Ptr *)ctx;
|
||||||
(*obj)->cancel();
|
(*obj)->cancel();
|
||||||
delete obj;
|
delete obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
class WorkThreadPoolForC : public TaskExecutorGetterImp {
|
||||||
|
public:
|
||||||
|
~WorkThreadPoolForC() override = default;
|
||||||
|
|
||||||
|
WorkThreadPoolForC(const char *name, size_t n_thread, int priority) {
|
||||||
|
//最低优先级
|
||||||
|
addPoller(name, n_thread, (ThreadPool::Priority) priority, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventPoller::Ptr getPoller() {
|
||||||
|
return dynamic_pointer_cast<EventPoller>(getExecutor());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
API_EXPORT mk_thread_pool API_CALL mk_thread_pool_create(const char *name, size_t n_thread, int priority) {
|
||||||
|
return new WorkThreadPoolForC(name, n_thread, priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_thread_pool_release(mk_thread_pool pool) {
|
||||||
|
assert(pool);
|
||||||
|
delete (WorkThreadPoolForC *) pool;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_thread API_CALL mk_thread_from_thread_pool(mk_thread_pool pool) {
|
||||||
|
assert(pool);
|
||||||
|
return ((WorkThreadPoolForC *) pool)->getPoller().get();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_sem API_CALL mk_sem_create() {
|
||||||
|
return new toolkit::semaphore;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_sem_release(mk_sem sem) {
|
||||||
|
assert(sem);
|
||||||
|
delete (toolkit::semaphore *) sem;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_sem_post(mk_sem sem, size_t n) {
|
||||||
|
assert(sem);
|
||||||
|
((toolkit::semaphore *) sem)->post(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_sem_wait(mk_sem sem) {
|
||||||
|
assert(sem);
|
||||||
|
((toolkit::semaphore *) sem)->wait();
|
||||||
}
|
}
|
196
api/source/mk_track.cpp
Normal file
196
api/source/mk_track.cpp
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mk_track.h"
|
||||||
|
#include "Extension/Track.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace toolkit;
|
||||||
|
using namespace mediakit;
|
||||||
|
|
||||||
|
class VideoTrackForC : public VideoTrack {
|
||||||
|
public:
|
||||||
|
VideoTrackForC(int codec_id, codec_args *args) {
|
||||||
|
_codec_id = (CodecId) codec_id;
|
||||||
|
if (args) {
|
||||||
|
_args = *args;
|
||||||
|
} else {
|
||||||
|
memset(&_args, 0, sizeof(_args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~VideoTrackForC() override = default;
|
||||||
|
|
||||||
|
int getVideoHeight() const override {
|
||||||
|
return _args.video.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getVideoWidth() const override {
|
||||||
|
return _args.video.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getVideoFps() const override {
|
||||||
|
return _args.video.fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecId getCodecId() const override {
|
||||||
|
return _codec_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ready() override {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Track::Ptr clone() override {
|
||||||
|
return std::make_shared<std::remove_reference<decltype(*this)>::type>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sdp::Ptr getSdp() override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CodecId _codec_id;
|
||||||
|
codec_args _args;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AudioTrackForC : public AudioTrackImp {
|
||||||
|
public:
|
||||||
|
~AudioTrackForC() override = default;
|
||||||
|
|
||||||
|
AudioTrackForC(int codec_id, codec_args *args) :
|
||||||
|
AudioTrackImp((CodecId) codec_id, args->audio.sample_rate, args->audio.channels, 16) {}
|
||||||
|
|
||||||
|
Track::Ptr clone() override {
|
||||||
|
return std::make_shared<std::remove_reference<decltype(*this)>::type>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sdp::Ptr getSdp() override {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
API_EXPORT mk_track API_CALL mk_track_create(int codec_id, codec_args *args) {
|
||||||
|
switch (getTrackType((CodecId) codec_id)) {
|
||||||
|
case TrackVideo: return new Track::Ptr(std::make_shared<VideoTrackForC>(codec_id, args));
|
||||||
|
case TrackAudio: return new Track::Ptr(std::make_shared<AudioTrackForC>(codec_id, args));
|
||||||
|
default: WarnL << "unrecognized codec:" << codec_id; return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_track_unref(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
delete (Track::Ptr *)track;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_track API_CALL mk_track_ref(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
return new Track::Ptr(*( (Track::Ptr *)track));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_codec_id(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
return (*((Track::Ptr *) track))->getCodecId();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT const char *API_CALL mk_track_codec_name(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
return (*((Track::Ptr *) track))->getCodecName();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_bit_rate(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
return (*((Track::Ptr *) track))->getBitRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void *API_CALL mk_track_add_delegate(mk_track track, on_mk_frame_out cb, void *user_data) {
|
||||||
|
assert(track && cb);
|
||||||
|
auto delegate = std::make_shared<FrameWriterInterfaceHelper>([cb, user_data](const Frame::Ptr &frame) {
|
||||||
|
cb(user_data, (mk_frame) &frame);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
(*((Track::Ptr *) track))->addDelegate(delegate);
|
||||||
|
return delegate.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_track_del_delegate(mk_track track, void *tag) {
|
||||||
|
assert(track && tag);
|
||||||
|
(*((Track::Ptr *) track))->delDelegate((FrameWriterInterface *) tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_track_input_frame(mk_track track, mk_frame frame) {
|
||||||
|
assert(track && frame);
|
||||||
|
(*((Track::Ptr *) track))->inputFrame((*((Frame::Ptr *) frame)));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_is_video(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
return (*((Track::Ptr *) track))->getTrackType() == TrackVideo;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_video_width(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
auto video = dynamic_pointer_cast<VideoTrack>((*((Track::Ptr *) track)));
|
||||||
|
if (video) {
|
||||||
|
return video->getVideoWidth();
|
||||||
|
}
|
||||||
|
WarnL << "not video track";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_video_height(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
auto video = dynamic_pointer_cast<VideoTrack>((*((Track::Ptr *) track)));
|
||||||
|
if (video) {
|
||||||
|
return video->getVideoHeight();
|
||||||
|
}
|
||||||
|
WarnL << "not video track";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_video_fps(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
auto video = dynamic_pointer_cast<VideoTrack>((*((Track::Ptr *) track)));
|
||||||
|
if (video) {
|
||||||
|
return video->getVideoFps();
|
||||||
|
}
|
||||||
|
WarnL << "not video track";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_audio_sample_rate(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
auto audio = dynamic_pointer_cast<AudioTrack>((*((Track::Ptr *) track)));
|
||||||
|
if (audio) {
|
||||||
|
return audio->getAudioSampleRate();
|
||||||
|
}
|
||||||
|
WarnL << "not audio track";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_audio_channel(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
auto audio = dynamic_pointer_cast<AudioTrack>((*((Track::Ptr *) track)));
|
||||||
|
if (audio) {
|
||||||
|
return audio->getAudioChannel();
|
||||||
|
}
|
||||||
|
WarnL << "not audio track";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_track_audio_sample_bit(mk_track track) {
|
||||||
|
assert(track);
|
||||||
|
auto audio = dynamic_pointer_cast<AudioTrack>((*((Track::Ptr *) track)));
|
||||||
|
if (audio) {
|
||||||
|
return audio->getAudioSampleBit();
|
||||||
|
}
|
||||||
|
WarnL << "not audio track";
|
||||||
|
return 0;
|
||||||
|
}
|
126
api/source/mk_transcode.cpp
Normal file
126
api/source/mk_transcode.cpp
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "mk_transcode.h"
|
||||||
|
#include "Extension/Track.h"
|
||||||
|
|
||||||
|
using namespace mediakit;
|
||||||
|
|
||||||
|
#ifdef ENABLE_FFMPEG
|
||||||
|
|
||||||
|
#include "Codec/Transcode.h"
|
||||||
|
|
||||||
|
API_EXPORT mk_decoder API_CALL mk_decoder_create(mk_track track, int thread_num) {
|
||||||
|
assert(track);
|
||||||
|
return new FFmpegDecoder(*((Track::Ptr *)track), thread_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_decoder_release(mk_decoder ctx, int flush_frame) {
|
||||||
|
assert(ctx);
|
||||||
|
auto decoder = (FFmpegDecoder *)ctx;
|
||||||
|
if (flush_frame) {
|
||||||
|
decoder->stopThread(false);
|
||||||
|
}
|
||||||
|
delete decoder;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_decoder_decode(mk_decoder ctx, mk_frame frame, int async, int enable_merge) {
|
||||||
|
assert(ctx && frame);
|
||||||
|
((FFmpegDecoder *)ctx)->inputFrame(*((Frame::Ptr *)frame), false, async, enable_merge);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_decoder_set_max_async_frame_size(mk_decoder ctx, size_t size) {
|
||||||
|
assert(ctx && size);
|
||||||
|
((FFmpegDecoder *)ctx)->setMaxTaskSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_decoder_set_cb(mk_decoder ctx, on_mk_decode cb, void *user_data) {
|
||||||
|
assert(ctx && cb);
|
||||||
|
((FFmpegDecoder *)ctx)->setOnDecode([cb, user_data](const FFmpegFrame::Ptr &pix_frame) {
|
||||||
|
cb(user_data, (mk_frame_pix)&pix_frame);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT const AVCodecContext *API_CALL mk_decoder_get_context(mk_decoder ctx) {
|
||||||
|
assert(ctx);
|
||||||
|
return ((FFmpegDecoder *)ctx)->getContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
API_EXPORT mk_frame_pix API_CALL mk_frame_pix_ref(mk_frame_pix frame) {
|
||||||
|
assert(frame);
|
||||||
|
return new FFmpegFrame::Ptr(*(FFmpegFrame::Ptr *)frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_frame_pix API_CALL mk_frame_pix_from_av_frame(AVFrame *frame) {
|
||||||
|
assert(frame);
|
||||||
|
return new FFmpegFrame::Ptr(std::make_shared<FFmpegFrame>(
|
||||||
|
std::shared_ptr<AVFrame>(av_frame_clone(frame), [](AVFrame *frame) { av_frame_free(&frame); })));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void API_CALL mk_frame_pix_unref(mk_frame_pix frame) {
|
||||||
|
assert(frame);
|
||||||
|
delete (FFmpegFrame::Ptr *)frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT AVFrame *API_CALL mk_frame_pix_get_av_frame(mk_frame_pix frame) {
|
||||||
|
assert(frame);
|
||||||
|
return (*(FFmpegFrame::Ptr *)frame)->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
API_EXPORT mk_swscale mk_swscale_create(int output, int width, int height) {
|
||||||
|
return new FFmpegSws((AVPixelFormat)output, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT void mk_swscale_release(mk_swscale ctx) {
|
||||||
|
delete (FFmpegSws *)ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int mk_swscale_input_frame(mk_swscale ctx, mk_frame_pix frame, uint8_t *data) {
|
||||||
|
return ((FFmpegSws *)ctx)->inputFrame(*(FFmpegFrame::Ptr *)frame, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT mk_frame_pix mk_swscale_input_frame2(mk_swscale ctx, mk_frame_pix frame) {
|
||||||
|
return new FFmpegFrame::Ptr(((FFmpegSws *)ctx)->inputFrame(*(FFmpegFrame::Ptr *)frame));
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT uint8_t **API_CALL mk_get_av_frame_data(AVFrame *frame) {
|
||||||
|
return frame->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int *API_CALL mk_get_av_frame_line_size(AVFrame *frame) {
|
||||||
|
return frame->linesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int64_t API_CALL mk_get_av_frame_dts(AVFrame *frame) {
|
||||||
|
return frame->pkt_dts;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int64_t API_CALL mk_get_av_frame_pts(AVFrame *frame) {
|
||||||
|
return frame->pts;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_get_av_frame_width(AVFrame *frame) {
|
||||||
|
return frame->width;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_get_av_frame_height(AVFrame *frame) {
|
||||||
|
return frame->height;
|
||||||
|
}
|
||||||
|
|
||||||
|
API_EXPORT int API_CALL mk_get_av_frame_format(AVFrame *frame) {
|
||||||
|
return frame->format;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif //ENABLE_FFMPEG
|
6
api/tests/CMakeLists.sample
Normal file
6
api/tests/CMakeLists.sample
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.1.3)
|
||||||
|
project(player)
|
||||||
|
include_directories("../../include")
|
||||||
|
link_directories("../../so")
|
||||||
|
add_executable(player "./player_opencv.c")
|
||||||
|
target_link_libraries(player mk_api ssl crypto avcodec swscale swresample avutil x264 openh264 x265)
|
@ -22,14 +22,17 @@ static void s_on_exit(int sig) {
|
|||||||
exit_flag = 1;
|
exit_flag = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_h264_frame(void *user_data, mk_h264_splitter splitter, const char *frame, int size) {
|
static void on_h264_frame(void *user_data, mk_h264_splitter splitter, const char *data, int size) {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
Sleep(40);
|
Sleep(40);
|
||||||
#else
|
#else
|
||||||
usleep(40 * 1000);
|
usleep(40 * 1000);
|
||||||
#endif
|
#endif
|
||||||
mk_media media = (mk_media) user_data;
|
static int dts = 0;
|
||||||
mk_media_input_h264(media, frame, size, 0, 0);
|
mk_frame frame = mk_frame_create(MKCodecH264, dts, dts, data, size, NULL, NULL);
|
||||||
|
dts += 40;
|
||||||
|
mk_media_input_frame((mk_media) user_data, frame);
|
||||||
|
mk_frame_unref(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@ -60,7 +63,7 @@ int main(int argc, char *argv[]) {
|
|||||||
|
|
||||||
mk_media media = mk_media_create("__defaultVhost__", "live", "test", 0, 0, 0);
|
mk_media media = mk_media_create("__defaultVhost__", "live", "test", 0, 0, 0);
|
||||||
//h264的codec
|
//h264的codec
|
||||||
mk_media_init_video(media, 0, 0, 0, 0);
|
mk_media_init_video(media, 0, 0, 0, 0, 2 * 104 * 1024);
|
||||||
mk_media_init_complete(media);
|
mk_media_init_complete(media);
|
||||||
|
|
||||||
//创建h264分帧器
|
//创建h264分帧器
|
||||||
|
61
api/tests/httpclient.c
Normal file
61
api/tests/httpclient.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "mk_mediakit.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mk_sem sem;
|
||||||
|
mk_http_requester requester;
|
||||||
|
} Context;
|
||||||
|
|
||||||
|
static API_CALL void on_requester_complete(void *user_data, int code, const char *err_msg){
|
||||||
|
Context *ctx = (Context *)user_data;
|
||||||
|
log_debug("code: %d %s", code, err_msg);
|
||||||
|
size_t res_len = 0;
|
||||||
|
log_debug("response: %s %s", mk_http_requester_get_response_status(ctx->requester),
|
||||||
|
mk_http_requester_get_response_body(ctx->requester, &res_len));
|
||||||
|
mk_sem_post(ctx->sem, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
mk_config config = {
|
||||||
|
.ini = NULL,
|
||||||
|
.ini_is_path = 0,
|
||||||
|
.log_level = 0,
|
||||||
|
.log_mask = LOG_CONSOLE,
|
||||||
|
.ssl = NULL,
|
||||||
|
.ssl_is_path = 1,
|
||||||
|
.ssl_pwd = NULL,
|
||||||
|
.thread_num = 0
|
||||||
|
};
|
||||||
|
mk_env_init(&config);
|
||||||
|
|
||||||
|
mk_http_requester requester = mk_http_requester_create();
|
||||||
|
mk_http_requester_set_method(requester, "POST");
|
||||||
|
|
||||||
|
mk_http_body body = mk_http_body_from_string("tn=monline_7_dg&ie=utf-8&wd=test", 0);
|
||||||
|
mk_http_requester_set_body(requester, body);
|
||||||
|
mk_http_body_release(body);
|
||||||
|
|
||||||
|
mk_sem sem = mk_sem_create();
|
||||||
|
|
||||||
|
Context ctx = {.requester = requester, .sem = sem};
|
||||||
|
|
||||||
|
mk_http_requester_set_cb(requester, on_requester_complete, &ctx);
|
||||||
|
mk_http_requester_start(requester, "http://www.baidu.com/baidu", 10);
|
||||||
|
|
||||||
|
//等待http请求完毕
|
||||||
|
mk_sem_wait(sem);
|
||||||
|
|
||||||
|
mk_sem_release(sem);
|
||||||
|
mk_http_requester_release(requester);
|
||||||
|
return 0;
|
||||||
|
}
|
108
api/tests/player_opencv.c
Normal file
108
api/tests/player_opencv.c
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by MIT license that can be found in the
|
||||||
|
* LICENSE file in the root of the source tree. All contributing project authors
|
||||||
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "mk_mediakit.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
mk_player player;
|
||||||
|
mk_decoder video_decoder;
|
||||||
|
mk_swscale swscale;
|
||||||
|
} Context;
|
||||||
|
|
||||||
|
void API_CALL on_track_frame_out(void *user_data, mk_frame frame) {
|
||||||
|
Context *ctx = (Context *) user_data;
|
||||||
|
mk_decoder_decode(ctx->video_decoder, frame, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void API_CALL on_frame_decode(void *user_data, mk_frame_pix frame) {
|
||||||
|
Context *ctx = (Context *) user_data;
|
||||||
|
int w = mk_get_av_frame_width(mk_frame_pix_get_av_frame(frame));
|
||||||
|
int h = mk_get_av_frame_height(mk_frame_pix_get_av_frame(frame));
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
uint8_t *brg24 = malloc(w * h * 3);
|
||||||
|
mk_swscale_input_frame(ctx->swscale, frame, brg24);
|
||||||
|
free(brg24);
|
||||||
|
#else
|
||||||
|
//todo 此处转换为opencv对象
|
||||||
|
cv::Mat *mat = new cv::Mat();
|
||||||
|
mat->create(h, w, CV_8UC3);
|
||||||
|
mk_swscale_input_frame(ctx->swscale, frame, (uint8_t *) mat->data);
|
||||||
|
#endif
|
||||||
|
log_trace("decode frame output, pts:%d, w:%d, h:%d", mk_get_av_frame_dts(mk_frame_pix_get_av_frame(frame)), w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void API_CALL on_mk_play_event_func(void *user_data, int err_code, const char *err_msg, mk_track tracks[],
|
||||||
|
int track_count) {
|
||||||
|
Context *ctx = (Context *) user_data;
|
||||||
|
if (err_code == 0) {
|
||||||
|
//success
|
||||||
|
log_debug("play success!");
|
||||||
|
for (int i = 0; i < track_count; ++i) {
|
||||||
|
if (mk_track_is_video(tracks[i])) {
|
||||||
|
log_info("got video track: %s", mk_track_codec_name(tracks[i]));
|
||||||
|
ctx->video_decoder = mk_decoder_create(tracks[i], 0);
|
||||||
|
mk_decoder_set_cb(ctx->video_decoder, on_frame_decode, user_data);
|
||||||
|
//监听track数据回调
|
||||||
|
mk_track_add_delegate(tracks[i], on_track_frame_out, user_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log_warn("play failed: %d %s", err_code, err_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void API_CALL on_mk_shutdown_func(void *user_data, int err_code, const char *err_msg, mk_track tracks[], int track_count) {
|
||||||
|
log_warn("play interrupted: %d %s", err_code, err_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
mk_config config = {
|
||||||
|
.ini = NULL,
|
||||||
|
.ini_is_path = 0,
|
||||||
|
.log_level = 0,
|
||||||
|
.log_mask = LOG_CONSOLE,
|
||||||
|
.ssl = NULL,
|
||||||
|
.ssl_is_path = 1,
|
||||||
|
.ssl_pwd = NULL,
|
||||||
|
.thread_num = 0
|
||||||
|
};
|
||||||
|
mk_env_init(&config);
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Usage: ./player url\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context ctx;
|
||||||
|
memset(&ctx, 0, sizeof(Context));
|
||||||
|
|
||||||
|
ctx.player = mk_player_create();
|
||||||
|
ctx.swscale = mk_swscale_create(3, 0, 0);
|
||||||
|
mk_player_set_on_result(ctx.player, on_mk_play_event_func, &ctx);
|
||||||
|
mk_player_set_on_shutdown(ctx.player, on_mk_shutdown_func, &ctx);
|
||||||
|
mk_player_play(ctx.player, argv[1]);
|
||||||
|
|
||||||
|
log_info("enter any key to exit");
|
||||||
|
getchar();
|
||||||
|
|
||||||
|
if (ctx.player) {
|
||||||
|
mk_player_release(ctx.player);
|
||||||
|
}
|
||||||
|
if (ctx.video_decoder) {
|
||||||
|
mk_decoder_release(ctx.video_decoder, 1);
|
||||||
|
}
|
||||||
|
if (ctx.swscale) {
|
||||||
|
mk_swscale_release(ctx.swscale);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
@ -8,16 +8,9 @@
|
|||||||
* may be found in the AUTHORS file in the root of the source tree.
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "mk_mediakit.h"
|
#include "mk_mediakit.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include "windows.h"
|
|
||||||
#else
|
|
||||||
#include "unistd.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mk_player player;
|
mk_player player;
|
||||||
mk_media media;
|
mk_media media;
|
||||||
@ -84,7 +77,12 @@ void API_CALL on_mk_media_source_regist_func(void *user_data, mk_media_source se
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void API_CALL on_mk_play_event_func(void *user_data, int err_code, const char *err_msg) {
|
void API_CALL on_track_frame_out(void *user_data, mk_frame frame) {
|
||||||
|
Context *ctx = (Context *) user_data;
|
||||||
|
mk_media_input_frame(ctx->media, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void API_CALL on_mk_play_event_func(void *user_data, int err_code, const char *err_msg, mk_track tracks[], int track_count) {
|
||||||
Context *ctx = (Context *) user_data;
|
Context *ctx = (Context *) user_data;
|
||||||
release_media(&(ctx->media));
|
release_media(&(ctx->media));
|
||||||
release_pusher(&(ctx->pusher));
|
release_pusher(&(ctx->pusher));
|
||||||
@ -92,21 +90,9 @@ void API_CALL on_mk_play_event_func(void *user_data, int err_code, const char *e
|
|||||||
//success
|
//success
|
||||||
log_debug("play success!");
|
log_debug("play success!");
|
||||||
ctx->media = mk_media_create("__defaultVhost__", "live", "test", 0, 0, 0);
|
ctx->media = mk_media_create("__defaultVhost__", "live", "test", 0, 0, 0);
|
||||||
|
for (int i = 0; i < track_count; ++i) {
|
||||||
int video_codec = mk_player_video_codec_id(ctx->player);
|
mk_media_init_track(ctx->media, tracks[i]);
|
||||||
int audio_codec = mk_player_audio_codec_id(ctx->player);
|
mk_track_add_delegate(tracks[i], on_track_frame_out, user_data);
|
||||||
if(video_codec != -1){
|
|
||||||
mk_media_init_video(ctx->media, video_codec,
|
|
||||||
mk_player_video_width(ctx->player),
|
|
||||||
mk_player_video_height(ctx->player),
|
|
||||||
mk_player_video_fps(ctx->player));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(audio_codec != -1){
|
|
||||||
mk_media_init_audio(ctx->media,audio_codec,
|
|
||||||
mk_player_audio_samplerate(ctx->player),
|
|
||||||
mk_player_audio_channel(ctx->player),
|
|
||||||
mk_player_audio_bit(ctx->player));
|
|
||||||
}
|
}
|
||||||
mk_media_init_complete(ctx->media);
|
mk_media_init_complete(ctx->media);
|
||||||
mk_media_set_on_regist(ctx->media, on_mk_media_source_regist_func, ctx);
|
mk_media_set_on_regist(ctx->media, on_mk_media_source_regist_func, ctx);
|
||||||
@ -116,49 +102,15 @@ void API_CALL on_mk_play_event_func(void *user_data, int err_code, const char *e
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void API_CALL on_mk_play_data_func(void *user_data,int track_type, int codec_id,void *data,size_t len, uint32_t dts,uint32_t pts){
|
|
||||||
Context *ctx = (Context *) user_data;
|
|
||||||
switch (codec_id) {
|
|
||||||
case 0 : {
|
|
||||||
//h264
|
|
||||||
mk_media_input_h264(ctx->media, data, (int)len, dts, pts);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1 : {
|
|
||||||
//h265
|
|
||||||
mk_media_input_h265(ctx->media, data, (int)len, dts, pts);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 2 : {
|
|
||||||
//aac, aac头7个字节
|
|
||||||
mk_media_input_aac(ctx->media, (uint8_t*)data + 7, (int)len, dts, data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3 : //g711a
|
|
||||||
case 4 : //g711u
|
|
||||||
case 5 : //opus
|
|
||||||
mk_media_input_audio(ctx->media, data, (int) len, dts);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default: {
|
|
||||||
log_warn("unknown codec: %d", codec_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void context_start(Context *ctx, const char *url_pull, const char *url_push){
|
void context_start(Context *ctx, const char *url_pull, const char *url_push){
|
||||||
release_player(&(ctx->player));
|
release_player(&(ctx->player));
|
||||||
ctx->player = mk_player_create();
|
ctx->player = mk_player_create();
|
||||||
mk_player_set_on_result(ctx->player, on_mk_play_event_func, ctx);
|
mk_player_set_on_result(ctx->player, on_mk_play_event_func, ctx);
|
||||||
mk_player_set_on_shutdown(ctx->player, on_mk_play_event_func, ctx);
|
mk_player_set_on_shutdown(ctx->player, on_mk_play_event_func, ctx);
|
||||||
mk_player_set_on_data(ctx->player, on_mk_play_data_func, ctx);
|
|
||||||
mk_player_play(ctx->player, url_pull);
|
mk_player_play(ctx->player, url_pull);
|
||||||
strcpy(ctx->push_url, url_push);
|
strcpy(ctx->push_url, url_push);
|
||||||
}
|
}
|
||||||
|
|
||||||
//create_player("http://hls.weathertv.cn/tslslive/qCFIfHB/hls/live_sd.m3u8");
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]){
|
int main(int argc, char *argv[]){
|
||||||
mk_config config = {
|
mk_config config = {
|
||||||
.ini = NULL,
|
.ini = NULL,
|
||||||
@ -172,6 +124,11 @@ int main(int argc, char *argv[]){
|
|||||||
};
|
};
|
||||||
mk_env_init(&config);
|
mk_env_init(&config);
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
printf("Usage: ./pusher.c pull_url push_url\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
//可以通过
|
//可以通过
|
||||||
//rtmp://127.0.0.1/live/test
|
//rtmp://127.0.0.1/live/test
|
||||||
//rtsp://127.0.0.1/live/test
|
//rtsp://127.0.0.1/live/test
|
||||||
@ -179,20 +136,14 @@ int main(int argc, char *argv[]){
|
|||||||
mk_rtsp_server_start(554, 0);
|
mk_rtsp_server_start(554, 0);
|
||||||
mk_rtmp_server_start(1935, 0);
|
mk_rtmp_server_start(1935, 0);
|
||||||
|
|
||||||
Context *ctx = (Context *)malloc(sizeof(Context));
|
Context *ctx = (Context *) malloc(sizeof(Context));
|
||||||
memset(ctx, 0, sizeof(Context));
|
memset(ctx, 0, sizeof(Context));
|
||||||
|
|
||||||
//推流给自己测试,当然也可以推流给其他服务器测试
|
//推流给自己测试,当然也可以推流给其他服务器测试
|
||||||
context_start(ctx, "http://hls.weathertv.cn/tslslive/qCFIfHB/hls/live_sd.m3u8", "rtsp://127.0.0.1/live/rtsp_push");
|
context_start(ctx, argv[1], argv[2]);
|
||||||
|
|
||||||
int i = 10 * 60;
|
log_info("enter any key to exit");
|
||||||
while(--i){
|
getchar();
|
||||||
#ifdef _WIN32
|
|
||||||
Sleep(1000);
|
|
||||||
#else
|
|
||||||
sleep(1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
release_context(&ctx);
|
release_context(&ctx);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -8,18 +8,8 @@
|
|||||||
* may be found in the AUTHORS file in the root of the source tree.
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "mk_mediakit.h"
|
#include "mk_mediakit.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include "windows.h"
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "unistd.h"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LOG_LEV 4
|
#define LOG_LEV 4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -396,10 +386,6 @@ void API_CALL on_mk_flow_report(const mk_media_info url_info,
|
|||||||
(int)mk_sock_info_peer_port(sender));
|
(int)mk_sock_info_peer_port(sender));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int flag = 1;
|
|
||||||
static void s_on_exit(int sig){
|
|
||||||
flag = 0;
|
|
||||||
}
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
char *ini_path = mk_util_get_exe_dir("c_api.ini");
|
char *ini_path = mk_util_get_exe_dir("c_api.ini");
|
||||||
char *ssl_path = mk_util_get_exe_dir("ssl.p12");
|
char *ssl_path = mk_util_get_exe_dir("ssl.p12");
|
||||||
@ -444,17 +430,11 @@ int main(int argc, char *argv[]) {
|
|||||||
.on_mk_flow_report = on_mk_flow_report
|
.on_mk_flow_report = on_mk_flow_report
|
||||||
};
|
};
|
||||||
mk_events_listen(&events);
|
mk_events_listen(&events);
|
||||||
|
|
||||||
log_info("media server %s", "stared!");
|
log_info("media server %s", "stared!");
|
||||||
|
|
||||||
signal(SIGINT, s_on_exit );// 设置退出信号
|
log_info("enter any key to exit");
|
||||||
while (flag) {
|
getchar();
|
||||||
#ifdef _WIN32
|
|
||||||
Sleep(1000);
|
|
||||||
#else
|
|
||||||
sleep(1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
mk_stop_all_server();
|
mk_stop_all_server();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -8,26 +8,15 @@
|
|||||||
* may be found in the AUTHORS file in the root of the source tree.
|
* may be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "mk_mediakit.h"
|
#include "mk_mediakit.h"
|
||||||
#ifdef _WIN32
|
|
||||||
#include "windows.h"
|
|
||||||
#else
|
|
||||||
#include "unistd.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define LOG_LEV 4
|
#define LOG_LEV 4
|
||||||
//修改此宏,可以选择协议类型
|
//修改此宏,可以选择协议类型
|
||||||
#define TCP_TYPE mk_type_ws
|
#define TCP_TYPE mk_type_ws
|
||||||
|
|
||||||
static int flag = 1;
|
|
||||||
static void s_on_exit(int sig){
|
|
||||||
flag = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mk_tcp_session _session;
|
mk_tcp_session _session;
|
||||||
@ -52,11 +41,15 @@ void API_CALL on_mk_tcp_session_create(uint16_t server_port,mk_tcp_session sessi
|
|||||||
* @param data 数据指针
|
* @param data 数据指针
|
||||||
* @param len 数据长度
|
* @param len 数据长度
|
||||||
*/
|
*/
|
||||||
void API_CALL on_mk_tcp_session_data(uint16_t server_port,mk_tcp_session session,const char *data,size_t len){
|
void API_CALL on_mk_tcp_session_data(uint16_t server_port,mk_tcp_session session, mk_buffer buffer){
|
||||||
char ip[64];
|
char ip[64];
|
||||||
log_printf(LOG_LEV,"from %s %d, data[%d]: %s",mk_tcp_session_peer_ip(session,ip),(int)mk_tcp_session_peer_port(session), len,data);
|
log_printf(LOG_LEV,"from %s %d, data[%d]: %s",
|
||||||
|
mk_tcp_session_peer_ip(session,ip),
|
||||||
|
(int)mk_tcp_session_peer_port(session),
|
||||||
|
mk_buffer_get_size(buffer),
|
||||||
|
mk_buffer_get_data(buffer));
|
||||||
mk_tcp_session_send(session,"echo:",0);
|
mk_tcp_session_send(session,"echo:",0);
|
||||||
mk_tcp_session_send(session,data,len);
|
mk_tcp_session_send_buffer(session, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -129,8 +122,8 @@ void API_CALL on_mk_tcp_client_disconnect(mk_tcp_client client,int code,const ch
|
|||||||
* @param data 数据指针
|
* @param data 数据指针
|
||||||
* @param len 数据长度
|
* @param len 数据长度
|
||||||
*/
|
*/
|
||||||
void API_CALL on_mk_tcp_client_data(mk_tcp_client client,const char *data,size_t len){
|
void API_CALL on_mk_tcp_client_data(mk_tcp_client client, mk_buffer buffer){
|
||||||
log_printf(LOG_LEV,"data[%d]:%s",len,data);
|
log_printf(LOG_LEV, "data[%d]:%s", mk_buffer_get_size(buffer), mk_buffer_get_data(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -203,14 +196,9 @@ int main(int argc, char *argv[]) {
|
|||||||
test_server();
|
test_server();
|
||||||
test_client();
|
test_client();
|
||||||
|
|
||||||
signal(SIGINT, s_on_exit );// 设置退出信号
|
log_info("enter any key to exit");
|
||||||
while (flag) {
|
getchar();
|
||||||
#ifdef _WIN32
|
|
||||||
Sleep(1000);
|
|
||||||
#else
|
|
||||||
sleep(1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
mk_stop_all_server();
|
mk_stop_all_server();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -91,6 +91,9 @@ bool FrameMerger::willFlush(const Frame::Ptr &frame) const{
|
|||||||
//缓存为空
|
//缓存为空
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!frame) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case none : {
|
case none : {
|
||||||
//frame不是完整的帧,我们合并为一帧
|
//frame不是完整的帧,我们合并为一帧
|
||||||
@ -180,6 +183,10 @@ bool FrameMerger::inputFrame(const Frame::Ptr &frame, const onOutput &cb, Buffer
|
|||||||
_have_decode_able_frame = false;
|
_have_decode_able_frame = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!frame) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame->decodeAble()) {
|
if (frame->decodeAble()) {
|
||||||
_have_decode_able_frame = true;
|
_have_decode_able_frame = true;
|
||||||
}
|
}
|
||||||
|
@ -310,45 +310,33 @@ private:
|
|||||||
*/
|
*/
|
||||||
class FrameDispatcher : public FrameWriterInterface {
|
class FrameDispatcher : public FrameWriterInterface {
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<FrameDispatcher> Ptr;
|
using Ptr = std::shared_ptr<FrameDispatcher>;
|
||||||
|
FrameDispatcher() = default;
|
||||||
FrameDispatcher(){}
|
~FrameDispatcher() override = default;
|
||||||
virtual ~FrameDispatcher(){}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加代理
|
* 添加代理
|
||||||
*/
|
*/
|
||||||
void addDelegate(const FrameWriterInterface::Ptr &delegate){
|
void addDelegate(const FrameWriterInterface::Ptr &delegate) {
|
||||||
//_delegates_write可能多线程同时操作
|
|
||||||
std::lock_guard<std::mutex> lck(_mtx);
|
std::lock_guard<std::mutex> lck(_mtx);
|
||||||
_delegates_write.emplace(delegate.get(),delegate);
|
_delegates.emplace(delegate.get(), delegate);
|
||||||
_need_update = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除代理
|
* 删除代理
|
||||||
*/
|
*/
|
||||||
void delDelegate(FrameWriterInterface *ptr){
|
void delDelegate(FrameWriterInterface *ptr) {
|
||||||
//_delegates_write可能多线程同时操作
|
|
||||||
std::lock_guard<std::mutex> lck(_mtx);
|
std::lock_guard<std::mutex> lck(_mtx);
|
||||||
_delegates_write.erase(ptr);
|
_delegates.erase(ptr);
|
||||||
_need_update = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 写入帧并派发
|
* 写入帧并派发
|
||||||
*/
|
*/
|
||||||
bool inputFrame(const Frame::Ptr &frame) override{
|
bool inputFrame(const Frame::Ptr &frame) override {
|
||||||
if(_need_update){
|
std::lock_guard<std::mutex> lck(_mtx);
|
||||||
//发现代理列表发生变化了,这里同步一次
|
|
||||||
std::lock_guard<std::mutex> lck(_mtx);
|
|
||||||
_delegates_read = _delegates_write;
|
|
||||||
_need_update = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//_delegates_read能确保是单线程操作的
|
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
for (auto &pr : _delegates_read) {
|
for (auto &pr : _delegates) {
|
||||||
if (pr.second->inputFrame(frame)) {
|
if (pr.second->inputFrame(frame)) {
|
||||||
ret = true;
|
ret = true;
|
||||||
}
|
}
|
||||||
@ -360,13 +348,18 @@ public:
|
|||||||
* 返回代理个数
|
* 返回代理个数
|
||||||
*/
|
*/
|
||||||
size_t size() const {
|
size_t size() const {
|
||||||
return _delegates_write.size();
|
std::lock_guard<std::mutex> lck(_mtx);
|
||||||
|
return _delegates.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
std::lock_guard<std::mutex> lck(_mtx);
|
||||||
|
_delegates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::mutex _mtx;
|
mutable std::mutex _mtx;
|
||||||
std::map<void *,FrameWriterInterface::Ptr> _delegates_read;
|
std::map<void *, FrameWriterInterface::Ptr> _delegates;
|
||||||
std::map<void *,FrameWriterInterface::Ptr> _delegates_write;
|
|
||||||
bool _need_update = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user