const 发布的文章

“const”

最近,互联网舆论场上时有出现所谓“历史的垃圾时间”论调。这一论调的核心观点是:历史的某个时刻注定将无所作为,不以个人意志为转变。不少大V、博主看这个说法“时髦”,又传言有某西方经济学家的理论作“背书”,于是不问真假草率引用,继而炮制出大量“躺平”“看戏”的论调。

“垃圾时间”这个说法常出现在球赛解说中,一般是指比分悬殊过大、难以扭转局面的时候。但是上升到历史的高度,是否还能这样类比?有学者较真,不仅精读了被传为观点出处的某篇经济学文章,更翻遍了该作者的代表性著作,也未发现“垃圾时间”这一提法的影子。
截图 2024-07-17 10-17-19.png
没有理论依据,却能“横空出世”,“历史的垃圾时间”成为“顶流”话题,精准迎合了互联网上一些人“语不惊人死不休”“先讲情绪再讲理”的传播偏好,充满了推波助澜的痕迹。这个理论不讲具体问题,而是用宏大的叙事背景,杂糅个体的人生感受,偷换概念、制造焦虑。更有一些人借题发挥,把“历史的垃圾时间”变成叙事陷阱和观点病毒,将最终落脚点指向唱空中国的经济社会发展。

这些年来,一些西方国家持续对中国开展认知战,西方媒体描述的中国,时而发展见顶,时而产能过剩,时而威胁世界,时而行将崩溃。观点自相矛盾,却一次都没应验,何故?因为真实的中国,不在“另一个世界”。今年以来,“中国游”成为全球“热搜密码”,大量外国游客来到中国,感受大好风光、繁荣街市和便利生活。这些赞叹中国“好City呀”的外国游客,也绝不会认为中国处在“历史的垃圾时间”。今天的中国,有太多“月球挖土”“太空养鱼”的故事可供讲述,如果只盯着发展中的问题、转型中的痛点大谈“垃圾论”,是何居心不言而喻。

经济虽有周期波动,但历史绝无垃圾时间。新中国成立特别是改革开放以来,中国用几十年时间走完西方发达国家几百年走过的工业化历程,创造出经济快速发展和社会长期稳定的奇迹。细看其中每一个具体时期,摆在中国人面前的都是难以想象的巨大困难——一穷二白、全面封锁、技术壁垒……但中国人用不服输、不信邪的劲头,硬生生蹚出一条中华民族伟大复兴的道路。有这样逢山开路遇水搭桥的精气神,我们还怕什么历史宿命论?

当然,“高光时刻”不等同于一帆风顺,好时代也不是运气好而赶上的,而是无数时代参与者一同奋斗出来的。活在当下的人作为历史创造者与时代同行,千千万万的人共同影响着历史走向。当前,我们正处于一场新的技术革命的开端,新的技术、新的职业、新的产业、新的梦想正在持续涌现。用自身奋斗的确定性对抗未来的不确定性,而不是直接躺平、置身事外地“定义”历史,这才是百年未有之大变局中,我们这代人应该扛起的担当。历史是人民书写的,人民群众是历史的创造者。历史的定义权不在少数人手中,用积极向上的奋斗姿态回应时代的呼唤,每个人都可以站上人生出彩的舞台,成为书写历史的主角。

袁 媛

https://jsnews.jschina.com.cn/jsyw/202407/t20240717_3434157.shtml

#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