分类 云笔记 下的文章

“收集其他网站上看到的点滴内容。”

#include <gst/gst.h>
 
#include <string.h>
 
#include <gst/app/gstappsrc.h>
#include <gst/app/gstappsink.h>
 
/* these are the caps we are going to pass through the appsink and appsrc */
const gchar *audio_caps =
    "audio/x-raw,format=S16LE,channels=2,rate=44100,layout=interleaved";
 
#define DEVICE "alsa_output.pci-0000_00_05.0.analog-stereo.monitor"
 
#define APPSRC_PULL_MODE (0)  /* appsrc working in pull mode or not */
#define PLAY_FILE (0)     /* play file or get data from pulseaudio */
#define SAVE_FILE (1)     /* save a file or playing directly */
static GstBuffer* s_app_buffer = NULL;
 
typedef struct
{
    GMainLoop *loop;
    GstElement *sink_pipeline;
    GstElement *src_pipeline;
} ProgramData;
 
/* called when the appsink notifies us that there is a new buffer ready for
 * processing */
static GstFlowReturn
on_new_sample_from_sink (GstElement * sink_elm, ProgramData * data)
{
    GstSample *sample = NULL;
    GstBuffer *buffer, *app_buffer;
    GstElement *sink, *source;
    GstFlowReturn ret;
    GstMapInfo map;
    
    /* get the sample from appsink */
    //sample = gst_app_sink_pull_sample (GST_APP_SINK (sink_elm));
#if 0
    sink = gst_bin_get_by_name (GST_BIN (data->src_pipeline), "testsink");
    g_signal_emit_by_name (sink, "pull-sample", &sample, &ret);
    gst_object_unref (sink);
#else
    g_signal_emit_by_name(sink_elm, "pull-sample", &sample, &ret);
#endif
 
    if(sample){
        buffer = gst_sample_get_buffer (sample);
        g_print("on_new_sample_from_sink() call!; size = %d\n", gst_buffer_get_size(buffer));
    }
    else{
        g_print("sample is NULL \n");
        return ret;
    }
 
 
    /* 查看pull 到的sample 数据 */
#if 0
    /* Mapping a buffer can fail (non-readable) */
    if (gst_buffer_map (buffer, &map, GST_MAP_READ)) {
        /* print the buffer data for debug */
        int i = 0, j = 0;
        for(; i < 10; i++)         
              g_print("%x ", map.data[i]);
        g_print("\n");
    }
#endif
 
    /* make a copy */
#if !APPSRC_PULL_MODE
    app_buffer = gst_buffer_copy (buffer);
#else
    s_app_buffer = gst_buffer_copy(buffer);
#endif
 
    /* we don't need the appsink sample anymore */
    gst_sample_unref (sample);
 
    /* 如果appsrc 为push 模式,直接将数据注入给appsrc */
    /* get source an push new buffer */
#if !APPSRC_PULL_MODE
    source = gst_bin_get_by_name (GST_BIN (data->sink_pipeline), "testsource");
    //ret = gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);
    g_signal_emit_by_name( source, "push-buffer", app_buffer, &ret );//数据送入pipeline
    gst_object_unref (source);
    gst_buffer_unref(app_buffer);
#endif
 
    return ret;
}
 
/* called when we get a GstMessage from the source pipeline when we get EOS, we
 * notify the appsrc of it. */
static gboolean
on_appsink_message (GstBus * bus, GstMessage * message, ProgramData * data)
{
    GstElement *source;
 
    switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_EOS:
            g_print ("The source got dry\n");
            source = gst_bin_get_by_name (GST_BIN (data->sink_pipeline), "testsource");
            //gst_app_src_end_of_stream (GST_APP_SRC (source));
            g_signal_emit_by_name (source, "end-of-stream", NULL);
            gst_object_unref (source);
            break;
        case GST_MESSAGE_ERROR:
            g_print ("Received error\n");
            g_main_loop_quit (data->loop);
            break;
        default:
            break;
    }
    return TRUE;
}
 
 
/* called when we get a GstMessage from the sink pipeline when we get EOS, we
 * exit the mainloop and this testapp. */
static gboolean
on_appsrc_message (GstBus * bus, GstMessage * message, ProgramData * data)
{
    /* nil */
    switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_EOS:
            g_print ("Finished playback\n");
            g_main_loop_quit (data->loop);
            break;
        case GST_MESSAGE_ERROR:
            g_print ("Received error\n");
            g_main_loop_quit (data->loop);
            break;
        default:
            break;
    }
    return TRUE;
}
 
static gboolean read_data(ProgramData* app_data)
{
    GstElement *appsink;
    appsink = gst_bin_get_by_name (GST_BIN (app_data->src_pipeline), "testsink");
    GstFlowReturn ret = on_new_sample_from_sink(appsink, app_data);
    gst_object_unref(appsink);
 
    GstElement *source = NULL;
    if(s_app_buffer){
        g_print("read data()....\n");
        source = gst_bin_get_by_name (GST_BIN (app_data->sink_pipeline), "testsource");
        //ret = gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer);
        g_signal_emit_by_name( source, "push-buffer", s_app_buffer, &ret );//数据送入pipeline
        gst_object_unref (source);
        gst_buffer_unref(s_app_buffer);
        s_app_buffer = NULL;
    }
    else{
        g_print("read_data() s_app_buffer is NULL\n");
    }
    return TRUE;
}
 
static void on_appsrc_need_data(GstElement *appsrc,
                                                              guint unused_size,
                                                              ProgramData* app_data)
{
    g_print("on_appsrc_need_data() call !!!\n");
    guint src_id = g_idle_add ((GSourceFunc) read_data, app_data);
    return;
}
 
int main (int argc, char *argv[])
{
    gchar *filename = NULL;
    ProgramData *data = NULL;
    gchar *string = NULL;
    GstBus *bus = NULL;
    GstElement *testsink = NULL;
    GstElement *testsource = NULL;
 
    gst_init (&argc, &argv);
 
    if (argc == 2)
        filename = g_strdup (argv[1]);
    else
        filename = g_strdup ("xxx/xxxx.wav");
 
    if (!g_file_test (filename, G_FILE_TEST_EXISTS)) {
        g_print ("File %s does not exist\n", filename);
        return -1;
    }
 
    data = g_new0 (ProgramData, 1);
 
    data->loop = g_main_loop_new (NULL, FALSE);
 
    /* setting up source pipeline, we read from a file and convert to our desired
    * caps. */
 
#if PLAY_FILE  /* 播放wav 歌曲 */
    string =
      g_strdup_printf
      ("filesrc location=\"%s\" ! wavparse ! audioconvert ! appsink caps=\"%s\" name=testsink",
      filename, audio_caps);
#else  /* 从pulseaudio 抓取 */
    string =
      g_strdup_printf
      ("pulsesrc device=%s ! audioconvert ! appsink caps=\"%s\" name=testsink",
      DEVICE, audio_caps);
#endif
 
    g_free (filename);
    g_print("%s\n", string);
    data->src_pipeline = gst_parse_launch (string, NULL);
    g_free (string);
 
    if (data->src_pipeline == NULL) {
        g_print ("Bad source\n");
        return -1;
    }
 
    /* to be notified of messages from this pipeline, mostly EOS */
    bus = gst_element_get_bus (data->src_pipeline);
    gst_bus_add_watch (bus, (GstBusFunc) on_appsink_message, data);
    gst_object_unref (bus);
 
    /* we use appsink in push mode, it sends us a signal when data is available
    * and we pull out the data in the signal callback. We want the appsink to
    * push as fast as it can, hence the sync=false */
    testsink = gst_bin_get_by_name (GST_BIN (data->src_pipeline), "testsink");
    #if !APPSRC_PULL_MODE
    g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync", FALSE, NULL);
    g_signal_connect (testsink, "new-sample",
      G_CALLBACK (on_new_sample_from_sink), data);
    #endif
    gst_object_unref (testsink);
 
    /* setting up sink pipeline, we push audio data into this pipeline that will
    * then play it back using the default audio sink. We have no blocking
    * behaviour on the src which means that we will push the entire file into
    * memory. */
#if !SAVE_FILE
    string =
      g_strdup_printf ("appsrc name=testsource caps=\"%s\" ! autoaudiosink",
      audio_caps);
#else
    string =
      g_strdup_printf ("appsrc name=testsource caps=\"%s\" ! avenc_aac ! avmux_adts ! filesink location=sink_src.aac",
      audio_caps);
#endif
    data->sink_pipeline = gst_parse_launch (string, NULL);
    g_free (string);
 
    if (data->sink_pipeline == NULL) {
        g_print ("Bad sink\n");
        return -1;
    }
 
    testsource = gst_bin_get_by_name (GST_BIN (data->sink_pipeline), "testsource");
    /* configure for time-based format */
    g_object_set (testsource, "format", GST_FORMAT_TIME, NULL);
    /* uncomment the next line to block when appsrc has buffered enough */
    /* g_object_set (testsource, "block", TRUE, NULL); */
    #if APPSRC_PULL_MODE
    g_signal_connect (testsource, "need-data",
      G_CALLBACK (on_appsrc_need_data), data);
    #endif
    gst_object_unref (testsource);
 
    bus = gst_element_get_bus (data->sink_pipeline);
    gst_bus_add_watch (bus, (GstBusFunc) on_appsrc_message, data);
    gst_object_unref (bus);
 
    /* launching things */
    gst_element_set_state (data->src_pipeline, GST_STATE_PLAYING);
    gst_element_set_state (data->sink_pipeline, GST_STATE_PLAYING);
 
    /* let's run !, this loop will quit when the sink pipeline goes EOS or when an
    * error occurs in the source or sink pipelines. */
    g_print ("Let's run!\n");
    g_main_loop_run (data->loop);
    g_print ("Going out\n");
 
    gst_element_set_state (data->src_pipeline, GST_STATE_NULL);
    gst_element_set_state (data->sink_pipeline, GST_STATE_NULL);
 
    gst_object_unref (data->src_pipeline);
    gst_object_unref (data->sink_pipeline);
    g_main_loop_unref (data->loop);
    g_free (data);
 
    return 0;
}

据人民日报报道,中国劳动和社会保障科学研究院院长莫荣解读延迟退休改革时说,这是适应中国人均预期寿命、受教育年限普遍增加的客观情况,提升人力资源开发利用效益的需要;是适应劳动年龄人口变化,增加全社会劳动力有效供给的需要;也是适应劳动者就业意愿多样化的有效措施,有利于支持职业生涯自主规划选择。

莫荣说,“想早一些退休的职工,在满足养老保险最低缴费年限等条件下,可以选择弹性提前退休。有意愿、有能力、有条件继续工作的低龄老年人,也不用过早退出劳动力市场,可以选择继续工作。”

此外,会议还审议国防教育法修订草案、统计法修正草案等。

根据新华社报道,中国人力资源和社会保障部部长王晓萍对实施渐进式延迟法定退休年龄的决定草案作了说明。目前未公布具体实施办法。

中国十四届全国人大常委会第11次会议星期二(9月10日)举行,会议审议了国务院关于提请审议关于实施渐进式延迟法定退休年龄的决定草案的议案。“渐进式延迟法定退休年龄”星期二晚冲上微博热搜榜首。

中国华中科技大学的一项新研究表明,中国50岁劳动者的健康工作寿命期望值(HWLE)平均为6.87年。研究表明,中国50岁劳动者的总预期寿命(TLE)为30.06年,健康工作寿命期望值平均为6.87年。这意味着如果一个人在50岁后生存的30多年的时间里,预计只有约6.87年的时间处于既健康又工作的状态。健康工作寿命期望值还存在性别、社会经济和地域上的差异。文章建议,改进“一刀切”延长退休年龄的方式。

中国官方首次将“自愿、弹性”列为延迟法定退休年龄的基本原则,允许劳动者到法定退休年龄后继续工作。中国官方7月21日在三中全会结束后发布的《中共中央关于进一步全面深化改革 推进中国式现代化的决定》中,第46条提出积极应对人口老龄化,完善发展养老事业和养老产业政策机制。“按照自愿、弹性原则,稳妥有序推进渐进式延迟法定退休年龄改革。”第一财经报道指出,这是官方首次将”自愿、弹性”列为延迟退休原则。这意味着,劳动者到了法定退休年龄后,若劳动者身体健康愿意继续工作,雇主无权拒绝。中国目前法定退休年龄为女工人50岁,女干部55岁,男职工60岁。

下载源代码

git clone https://github.com/higithubhi/gstreamer-rgaconvert.git

编译源码:

进入gstreamer-rgaconvert目录

gcc -fPIC -shared plugins/gstrgaconvert.c -o libgstrgaconvert.so -I plugins/ -lrga -lgstallocators-1.0 -lgstreamer-1.0 -lglib-2.0 -lgobject-2.0 -lgstbase-1.0 -lgstvideo-1.0 -lgstaudio-1.0 -I/usr/include/glib-2.0 -I/usr/include/gstreamer-1.0 -I /usr/lib/aarch64-linux-gnu/glib-2.0/include/

复制生成后的文件

cp libgstrgaconvert.so /usr/lib/aarch64-linux-gnu/gstreamer-1.0/

查看是否生效

gst-inspect-1.0 |grep rgaconvert

rgaconvert: rgaconvert: Rockchip rga hardware convert

如是生效了就如上所示

测试解码转格式

gst-launch-1.0 filesrc location=1080p.mp4 ! qtdemux ! h264parse ! mppvideodec ! rgaconvert ! video/x-raw,format=NV12,width=1920,height=1080 ! fakesink sync=true

gst-launch-1.0 filesrc location=1080p.mp4 ! qtdemux ! h264parse ! mppvideodec ! rgaconvert ! video/x-raw,format=BGR,width=1920,height=1080 ! fakesink sync=true

gst-launch-1.0 filesrc location=1080p.mp4 ! qtdemux ! h264parse ! mppvideodec ! rgaconvert ! video/x-raw,format=RGB,width=1920,height=1080 ! fakesink sync=true

gst-launch-1.0 filesrc location=4k.mp4 ! qtdemux ! h264parse ! mppvideodec ! rgaconvert ! video/x-raw,format=BGR,width=3840,height=2160 ! fakesink sync=true
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
rga_api version 1.9.3_[2]
Pipeline is PREROLLED ...
Prerolled, waiting for async message to finish...
Setting pipeline to PLAYING ...
Redistribute latency...
New clock: GstSystemClock

创建RKNN-Toolkit2-2.0.0 Conda环境

创建RKNN-Toolkit2-2.0.0

conda create -n RKNN-Toolkit2-2.0.0 python=3.8

进入RKNN-Toolkit2-2.0.0

conda activate RKNN-Toolkit2-2.0.0

下载rknn-toolkit2

git clone https://github.com/airockchip/rknn-toolkit2.git

git clone https://github.com/airockchip/rknn-toolkit2.git
Cloning into 'rknn-toolkit2'...
remote: Enumerating objects: 2392, done.
remote: Counting objects: 100% (79/79), done.
remote: Compressing objects: 100% (32/32), done.
remote: Total 2392 (delta 54), reused 48 (delta 47), pack-reused 2313 (from 1)
Receiving objects: 100% (2392/2392), 2.31 GiB | 1.67 MiB/s, done.
Resolving deltas: 100% (847/847), done.
Updating files: 100% (1429/1429), done.

安装依赖

pip3 --default-timeout=500 install protobuf==3.20.3
pip3 --default-timeout=500 install psutil==5.9.0
pip3 --default-timeout=500 install ruamel.yaml==0.17.4
pip3 --default-timeout=500 install scipy==1.5.4
pip3 --default-timeout=500 install tqdm==4.64.0
pip3 --default-timeout=500 install opencv-python==4.5.5.64
pip3 --default-timeout=500 install fast-histogram==0.11
pip3 --default-timeout=500 install onnx==1.14.1
pip3 --default-timeout=500 install onnxoptimizer==0.2.7
pip3 --default-timeout=500 install onnxruntime==1.16.0
pip3 --default-timeout=500 install torch==1.10.1
pip3 --default-timeout=500 install tensorflow==2.8.0

继续安装

pip3 install packages/rknn_toolkit2-2.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Installing collected packages: rknn-toolkit2
Successfully installed rknn-toolkit2-2.2.0

验证安装

python3
Python 3.8.19 (default, Mar 20 2024, 19:58:24)
[GCC 11.2.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.

from rknn.api import RKNN

如果导入 RKNN 模块没有失败,说明安装成功

下载模型转换项目
RKNN Model Zoo基于RKNPU SDK 工具链开发, 提供了目前主流算法的部署例程. 例程包含导出RKNN模型, 使用Python API, CAPI 推理RKNN 模型的流程

git clone https://github.com/airockchip/rknn_model_zoo.git

也可以直接下载包

wget https://github.com/airockchip/rknn_model_zoo/archive/refs/tags/v2.2.0.tar.gz

Cloning into 'rknn_model_zoo'...
remote: Enumerating objects: 2846, done.
remote: Counting objects: 100% (618/618), done.
remote: Compressing objects: 100% (241/241), done.
remote: Total 2846 (delta 433), reused 475 (delta 367), pack-reused 2228 (from 1)
Receiving objects: 100% (2846/2846), 271.73 MiB | 1.67 MiB/s, done.
Resolving deltas: 100% (949/949), done.
Updating files: 100% (1409/1409), done.

进入目录

rknn_model_zoo/examples/yolov8/model

运行download.sh下载yolov8n.onnx包

wget -O ./yolov8n.onnx https://ftrg.zbox.filez.com/v2/delivery/data/95f00b0fc900458ba134f8b180b3f7a1/examples/yolov8/yolov8n.onnx

进入rknn_model_zoo/examples/yolov8/python

python convert.py yolov8n.onnx rk3588 i8 yolov8n.rknn

I rknn-toolkit2 version: 2.2.0
--> Config model
done
--> Loading model
I Loading : 100%|██████████████████████████████████████████████| 126/126 [00:00<00:00, 35533.00it/s]
done
--> Building model
.....
I rknn building ...
I rknn buiding done.
done
--> Export rknn model
done

查看生成的模型

md5sum yolov8n.rknn
c43e16c3d1d1a316ef36e08652b75061 yolov8n.rknn

在Ubuntu 22.04操作系统下启动虚拟机发现让Install vmmon和vmnet模块,点击安装,最后安装失败。

安装缺失模块

需要手动去编译缺失的vmmon和vmnet模块,依赖git开源仓库,获取仓库命令:

$ git clone https://github.com/mkubecek/vmware-host-modules
按照自己机器的vmware版本切换branch分支
$ cd vmware-host-modules
$ vmware-installer --list-products
Product Name Product Version
==================== ====================
vmware-player 17.5.0.22583795

$ git checkout workstation-17.5.1
开始编译和安装

$ sudo make
$ sudo make install

最后重新加载所有vmware模块服务

$ sudo /etc/init.d/vmware start

Starting VMware services:
Virtual machine monitor done
Virtual machine communication interface done
VM communication interface socket family done
Virtual ethernet done
VMware Authentication Daemon done
Shared Memory Available done

再点击运行vmware即可.