您当前的位置: 首页 >  c++

qianbo_insist

暂无认证

  • 0浏览

    0关注

    399博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

使用c++ 作为脚本语言制作协议转换中心

qianbo_insist 发布时间:2022-07-09 14:43:08 ,浏览量:0

如何使用c++ 作为脚本语言

首先底层可以使用angelscript,这一点无需质疑,不用再造轮子,因为作者做得比较好,测试的例子也非常好,同时,使用angelscript的游戏也是非常多的,下面简单先使用注册main 和测试函数来进行一个协议转换中心的制作,从而使得非c++ 的人员甚至前端也可以使用脚本c++来制作复杂的媒体工具和协议工具。 首先脚本如下所示:


int main()
{
    int x = 10;
    int y = 100;
    int c = x+y;
    string buffer1="";
    string buffer2 = buffer1+c;
    Print(buffer2);
    Print("\n");

    string xstr = tostring(x);
    Print(xstr+"\n");

    //rtsp地址和窗口地址
    int ret = rtsp("rtsp://192.168.1.129");
    
    string rtspret ="";
    rtspret+= ret;
    Print(rtspret+"\n");
    return 0;
}

和c,c++ 一样,main函数是入口,前面是一些测试函数,其中 1 tostring(int num) 2 rtsp(string url)

此2个函数都是自定义函数,也就是我们的api。rtsp函数表明我们需要拉取一个rtsp流,具体要干什么我们后面再说,如果成功则返回0 ,不成功则返回-1;

随着函数的扩展,例如文件系统的扩展,协议的扩展,我们就能做到使用脚本c++来建立程序,由于脚本在外面是txt,随时可以修改,保证了最大的灵活性。

注册函数

如何注册函数呢,在加载anglescript引擎以后,我们就可以注册自己的函数,注意这里并不是万能的,协议转换函数和媒体函数依然是要自己写的,不过是为了灵活性,我们需要把自己的组件完全标准化。

假定我们使用ffmpeg来制作rtsp程序

int rtsp(string &url) {
    AVFormatContext* format_ctx = avformat_alloc_context();
    AVCodecContext* pAVCodecContext_video = nullptr;
    AVCodec* pAVCodec_video = nullptr;
    AVCodecParameters* pAVCodePar_video = avcodec_parameters_alloc();
    AVPacket* pAVPacket = av_packet_alloc(); ;                                  
    AVFrame* pAVFrame_video = av_frame_alloc();                                     AVFrame* pAVFrameRGB32_video = av_frame_alloc();                          
    AVCodecParserContext* pAVCodeParseContext_video = nullptr;
    struct SwsContext* pSwsContext_video = nullptr;                                    	AVDictionary* opts = nullptr;
    int ret = -1;
    int numBytes = 0;                                                           // 解码后的数据长度
    uint8_t* outBuffer = nullptr;                                                // 解码后的数据存放缓存区
 // open rtsp: Open an input stream and read the header. The codecs are not opened
    //const char* url = "rtsp://admin:genepoint2020@192.168.100.14:554/cam/realmonitor?channel=1&subtype=0";
    av_dict_set(&opts, "rtsp_transport", "tcp", 0);
    av_dict_set(&opts, "stimeout", "2000000", 0);
    // audio/video stream index
    int video_stream_index = -1;
    ret = avformat_open_input(&format_ctx, url, nullptr, &opts);
    if (ret != 0) {
        fprintf(stderr, "fail to open url: %s, return value: %d\n", url, ret);
        return -1;
    }
    // Read packets of a media file to get stream information
    ret = avformat_find_stream_info(format_ctx, nullptr);
    if (ret nb_streams);
    for (int i = 0; i nb_streams; ++i) {
        const AVStream* stream = format_ctx->streams[i];
        fprintf(stdout, "type of the encoded data: %d\n", stream->codecpar->codec_id);
        if (stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_index = i;
            pAVCodePar_video = stream->codecpar;
            pAVCodec_video = avcodec_find_decoder(stream->codecpar->codec_id);
            if (!pAVCodec_video) {
                video_stream_index = -1;
                break;
            }
            pAVCodeParseContext_video = av_parser_init(pAVCodec_video->id);
            if (!pAVCodeParseContext_video) {
                video_stream_index = -1;
                break;
            }
            pAVCodecContext_video = avcodec_alloc_context3(pAVCodec_video);
            if (!pAVCodecContext_video) {
            }
            if (avcodec_open2(pAVCodecContext_video, pAVCodec_video, NULL) codecpar->width, stream->codecpar->height, stream->codecpar->format);
        }
    }
    if (video_stream_index == -1) {
        fprintf(stderr, "no video stream\n");
        return -1;
    }
    // 对拿到的原始数据格式进行缩放转换为指定的格式高宽大小
    pSwsContext_video = sws_getContext(
        pAVCodePar_video->width,
        pAVCodePar_video->height,
        static_cast(pAVCodePar_video->format),
        pAVCodePar_video->width,
        pAVCodePar_video->height,
        AV_PIX_FMT_RGBA,
        SWS_FAST_BILINEAR,
        nullptr,
        nullptr,
        nullptr
    );
    numBytes = av_image_get_buffer_size(
        AV_PIX_FMT_RGBA,
        pAVCodePar_video->width,
        pAVCodePar_video->height,
        1
    );
    outBuffer = (uint8_t*)av_malloc(numBytes);
    // pAVFrame32的data指针指向了outBuffer
     (
        pAVFrameRGB32_video->data,
        pAVFrameRGB32_video->linesize,
        outBuffer,
        AV_PIX_FMT_RGBA,
        pAVCodePar_video->width,
        pAVCodePar_video->height,
        1
    );
    while (1) {
        ret = av_read_frame(format_ctx, pAVPacket);
        if (ret stream_index == video_stream_index) {
            //            fprintf(stdout, "video stream, packet size: %d\n", pAVPacket->size);
            ret = avcodec_send_packet(pAVCodecContext_video, pAVPacket);
            if (0 != ret) {
                continue;
            }
            while (avcodec_receive_frame(pAVCodecContext_video, pAVFrame_video) == 0) {
                sws_scale(pSwsContext_video,
                    (const uint8_t* const*)pAVFrame_video->data,
                    pAVFrame_video->linesize,
                    0,
                    pAVCodePar_video->height,
                    pAVFrameRGB32_video->data,
                    pAVFrameRGB32_video->linesize);
                    //这里得到图像输出
                    //做其他操作
            }
        }
        av_packet_unref(pAVPacket);
    }
    av_parser_close(pAVCodeParseContext_video);
    av_frame_free(&pAVFrame_video);
    av_frame_free(&pAVFrameRGB32_video);
    av_free(outBuffer);
    av_free(pSwsContext_video);
    avcodec_free_context(&pAVCodecContext_video);
    avformat_close_input(&format_ctx);
    return  0;
}

上面这个函数如果正常运行是没有返回的,其实不对,这里是作为示例,我们制作一个加的rtsp 函数,简单一点,如下所示

string _to_string(int &y)
{
	string temp= std::to_string(y);
	return temp;
}
//you do here
int _rtsp(string& url)
{

	//your code here
	return (int)url.find("/");
}

两个注册函数完成,下面在引擎里注册一个函数


if( !strstr(asGetLibraryOptions(), "AS_MAX_PORTABILITY") )
	{
		// Register the functions that the scripts will be allowed to use.
		// Note how the return code is validated with an assert(). This helps
		// us discover where a problem occurs, and doesn't pollute the code
		// with a lot of if's. If an error occurs in release mode it will
		// be caught when a script is being built, so it is not necessary
		// to do the verification here as well.
		r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString), asCALL_CDECL); assert( r >= 0 );
		r = engine->RegisterGlobalFunction("uint GetSystemTime()", asFUNCTION(timeGetTime), asCALL_STDCALL); assert( r >= 0 );
		r = engine->RegisterGlobalFunction("string tostring(int &in)", asFUNCTION(_to_string), asCALL_CDECL); assert(r >= 0);
		r = engine->RegisterGlobalFunction("int rtsp(string &in)", asFUNCTION(_rtsp), asCALL_CDECL); assert(r >= 0);

	}

实现了这些函数就可以在脚本里面使用了。下面是整体代码:

#include   // cout
#include   // assert()
#include   // strstr()
#ifdef __linux__
	#include 
	#include 
	#include 
	#include 
#else
	#include    // kbhit(), getch()
	#include  // timeGetTime()
#endif
#include 
#include "../../../add_on/scriptstdstring/scriptstdstring.h"

using namespace std;

#ifdef __linux__

#define UINT unsigned int 
typedef unsigned int DWORD;

// Linux doesn't have timeGetTime(), this essentially does the same
// thing, except this is milliseconds since Epoch (Jan 1st 1970) instead
// of system start. It will work the same though...
DWORD timeGetTime()
{
	timeval time;
	gettimeofday(&time, NULL);
	return time.tv_sec*1000 + time.tv_usec/1000;
}

// Linux does have a getch() function in the curses library, but it doesn't
// work like it does on DOS. So this does the same thing, with out the need
// of the curses library.
int getch() 
{
	struct termios oldt, newt;
	int ch;

	tcgetattr(STDIN_FILENO, &oldt);
	newt = oldt;
	newt.c_lflag &= ~( ICANON | ECHO );
	tcsetattr( STDIN_FILENO, TCSANOW, &newt );

	ch = getchar();

	tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
	return ch;
}

#endif

// Function prototypes
int  RunApplication();
void ConfigureEngine(asIScriptEngine *engine);
int  CompileScript(asIScriptEngine *engine);
void PrintString(string &str);
void PrintString_Generic(asIScriptGeneric *gen);
void timeGetTime_Generic(asIScriptGeneric *gen);

string _to_string(int &y);
int _rtsp(string& url);
void LineCallback(asIScriptContext *ctx, DWORD *timeOut);

int main(int argc, char **argv)
{
	RunApplication();

	// Wait until the user presses a key
	cout message);
}


int RunApplication()
{
	int r;

	// Create the script engine
	asIScriptEngine *engine = asCreateScriptEngine();
	if( engine == 0 )
	{
		cout             
关注
打赏
1663161521
查看更多评论
0.2187s