mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-06-13 03:31:45 +08:00
全面更新整理c sdk
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "Util/logger.h"
|
||||
#include "Util/SSLBox.h"
|
||||
#include "Network/TcpServer.h"
|
||||
#include "Network/UdpServer.h"
|
||||
#include "Thread/WorkThreadPool.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;
|
||||
}
|
||||
|
||||
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);
|
||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||
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.iWidth = width;
|
||||
info.iHeight = height;
|
||||
info.iBitRate = bit_rate;
|
||||
(*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);
|
||||
}
|
||||
|
||||
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){
|
||||
assert(ctx);
|
||||
MediaHelper::Ptr *obj = (MediaHelper::Ptr *) ctx;
|
||||
(*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) {
|
||||
assert(ctx && data && len > 0);
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
assert(ctx && data && len > 0 && adts);
|
||||
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);
|
||||
_on_play = nullptr;
|
||||
_on_shutdown = nullptr;
|
||||
_on_data = nullptr;
|
||||
}
|
||||
|
||||
void onEvent(bool is_shutdown, const SockException &ex){
|
||||
lock_guard<recursive_mutex> lck(_mtx);
|
||||
if(is_shutdown){
|
||||
if (is_shutdown) {
|
||||
//播放中断
|
||||
if(_on_shutdown){
|
||||
_on_shutdown(_on_shutdown_data,ex.getErrCode(),ex.what());
|
||||
if (_on_shutdown) {
|
||||
_on_shutdown(_on_shutdown_data, ex.getErrCode(), ex.what(), nullptr, 0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//播放结果
|
||||
if(_on_play){
|
||||
_on_play(_on_play_data,ex.getErrCode(),ex.what());
|
||||
}
|
||||
|
||||
if(ex){
|
||||
//播放失败
|
||||
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;
|
||||
if (_on_play) {
|
||||
auto cpp_tracks = _player->getTracks(false);
|
||||
mk_track tracks[TrackMax] = {nullptr};
|
||||
int track_count = 0;
|
||||
for (auto &track : cpp_tracks) {
|
||||
tracks[track_count++] = (mk_track) &track;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
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());
|
||||
_on_play(_on_play_data, ex.getErrCode(), ex.what(), tracks, track_count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(){
|
||||
return _player;
|
||||
}
|
||||
@@ -119,12 +96,10 @@ private:
|
||||
MediaPlayer::Ptr _player;
|
||||
recursive_mutex _mtx;
|
||||
on_mk_play_event _on_play = nullptr;
|
||||
on_mk_play_data _on_data = nullptr;
|
||||
on_mk_play_event _on_shutdown = nullptr;
|
||||
|
||||
void *_on_play_data = nullptr;
|
||||
void *_on_shutdown_data = nullptr;
|
||||
void *_on_data_data = nullptr;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
assert(ctx);
|
||||
MediaPlayerForC &obj = **((MediaPlayerForC::Ptr *)ctx);
|
||||
|
||||
@@ -13,10 +13,76 @@
|
||||
#include "mk_tcp_private.h"
|
||||
#include "Http/WebSocketClient.h"
|
||||
#include "Http/WebSocketSession.h"
|
||||
#include "Network/Buffer.h"
|
||||
|
||||
using namespace toolkit;
|
||||
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){
|
||||
assert(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));
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_tcp_session_send(const mk_tcp_session ctx,const char *data, size_t len){
|
||||
assert(ctx && data);
|
||||
if(!len){
|
||||
len = strlen(data);
|
||||
}
|
||||
TcpSessionForC *session = (TcpSessionForC *)ctx;
|
||||
session->SockSender::send(data,len);
|
||||
API_EXPORT void API_CALL mk_tcp_session_send_buffer(const mk_tcp_session ctx, mk_buffer buffer) {
|
||||
assert(ctx && buffer);
|
||||
TcpSessionForC *session = (TcpSessionForC *) ctx;
|
||||
session->send(*((Buffer::Ptr *) buffer));
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_tcp_session_send_safe(const mk_tcp_session ctx,const char *data,size_t len){
|
||||
assert(ctx && data);
|
||||
if (!len) {
|
||||
len = strlen(data);
|
||||
}
|
||||
API_EXPORT void API_CALL mk_tcp_session_send(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(ctx, buffer);
|
||||
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 {
|
||||
std::weak_ptr<TcpSession> weak_session = ((TcpSessionForC *)ctx)->shared_from_this();
|
||||
std::string str = std::string(data,len);
|
||||
((TcpSessionForC *)ctx)->async([weak_session,str](){
|
||||
std::weak_ptr<TcpSession> weak_session = ((TcpSessionForC *) ctx)->shared_from_this();
|
||||
auto ref = mk_buffer_ref(buffer);
|
||||
((TcpSessionForC *) ctx)->async([weak_session, ref]() {
|
||||
auto session_session = weak_session.lock();
|
||||
if(session_session){
|
||||
session_session->SockSender::send(str);
|
||||
if (session_session) {
|
||||
session_session->send(*((Buffer::Ptr *) ref));
|
||||
}
|
||||
mk_buffer_unref(ref);
|
||||
});
|
||||
} catch (std::exception &ex) {
|
||||
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////////////////////////////////////////////////
|
||||
static TcpServer::Ptr s_tcp_server[4];
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void TcpClientForC::onRecv(const Buffer::Ptr &pBuf) {
|
||||
if(_events.on_mk_tcp_client_data){
|
||||
_events.on_mk_tcp_client_data(_client,pBuf->data(),pBuf->size());
|
||||
if (_events.on_mk_tcp_client_data) {
|
||||
_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);
|
||||
}
|
||||
|
||||
API_EXPORT void API_CALL mk_tcp_client_send(mk_tcp_client ctx, const char *data, int len){
|
||||
assert(ctx && data);
|
||||
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *)ctx;
|
||||
(*client)->SockSender::send(data,len);
|
||||
API_EXPORT void API_CALL mk_tcp_client_send_buffer(mk_tcp_client ctx, mk_buffer buffer) {
|
||||
assert(ctx && buffer);
|
||||
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *) ctx;
|
||||
(*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){
|
||||
assert(ctx && data);
|
||||
TcpClientForC::Ptr *client = (TcpClientForC::Ptr *)ctx;
|
||||
std::weak_ptr<TcpClient> weakClient = *client;
|
||||
auto buf = BufferRaw::create();
|
||||
buf->assign(data,len);
|
||||
(*client)->async([weakClient,buf](){
|
||||
auto strongClient = weakClient.lock();
|
||||
if(strongClient){
|
||||
strongClient->send(buf);
|
||||
}
|
||||
});
|
||||
auto buffer = mk_buffer_from_char(data, len, nullptr, nullptr);
|
||||
mk_tcp_client_send_buffer_safe(ctx, buffer);
|
||||
mk_buffer_unref(buffer);
|
||||
}
|
||||
|
||||
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){
|
||||
assert(ctx && cb);
|
||||
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;
|
||||
(*obj)->cancel();
|
||||
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
|
||||
Reference in New Issue
Block a user