2024/10/4

vlc open rtsp fail, server side error message

[INFO  rtsp_demo.c:408:rtsp_new_client_connection] new rtsp client 10.42.0.1:47890 comming
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
SETUP rtsp://10.42.0.63:554/live/0 RTSP/1.0
CSeq: 0
Transport: RTP/AVP;unicast;client_port=9298-9299

[DEBUG rtsp_demo.c:950:rtsp_handle_SETUP]
[WARN  rtsp_demo.c:980:rtsp_handle_SETUP] rtsp urlpath:/live/0 err
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 461 Unsupported Transport
CSeq: 0
Date: Fri Oct  4 16:17:52 2024
Server: rtsp_demo

[INFO  rtsp_demo.c:408:rtsp_new_client_connection] new rtsp client 10.42.0.1:47902 comming
[DEBUG rtsp_demo.c:1158:rtsp_recv_msg] peer closed
[INFO  rtsp_demo.c:427:rtsp_del_client_connection] delete client 86 from 10.42.0.1
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
OPTIONS rtsp://10.42.0.63:554 RTSP/1.0
CSeq: 1
User-Agent: RealMedia Player Version 6.0.9.1235 (linux-2.0-libc6-i386-gcc2.95)
ClientChallenge: 9e26d33f2984236010ef6253fb1887f7
PlayerStarttime: [28/03/2003:22:50:23 00:00]
CompanyID: KnKV4M4I/B2FjJ1TToLycw==
GUID: 00000000-0000-0000-0000-000000000000
RegionData: 0
ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586

[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: ClientChallenge: 9e26d33f2984236010ef6253fb1887f7
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: PlayerStarttime: [28/03/2003:22:50:23 00:00]
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: CompanyID: KnKV4M4I/B2FjJ1TToLycw==
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: GUID: 00000000-0000-0000-0000-000000000000
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: RegionData: 0
[WARN  rtsp_msg.c:888:rtsp_msg_parse_from_array] unknown line: ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586
[DEBUG rtsp_demo.c:725:rtsp_handle_OPTIONS]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 1
Date: Fri Oct  4 16:17:53 2024
Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN
Server: rtsp_demo

[DEBUG rtsp_demo.c:1158:rtsp_recv_msg] peer closed
[INFO  rtsp_demo.c:427:rtsp_del_client_connection] delete client 87 from 10.42.0.1

OK 的版本,使用 ffplay
ffplay "rtsp://10.42.0.254/live/0"
server 端 log
[INFO  rtsp_demo.c:408:rtsp_new_client_connection] new rtsp client 10.42.0.1:35114 comming
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
OPTIONS rtsp://10.42.0.254:554/live/0 RTSP/1.0
CSeq: 1
User-Agent: Lavf60.16.100

[DEBUG rtsp_demo.c:725:rtsp_handle_OPTIONS]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 1
Date: Fri Jan  1 12:16:08 2021
Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN
Server: rtsp_demo

[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
DESCRIBE rtsp://10.42.0.254:554/live/0 RTSP/1.0
Accept: application/sdp
CSeq: 2
User-Agent: Lavf60.16.100

[DEBUG rtsp_demo.c:746:rtsp_handle_DESCRIBE]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 2
Date: Fri Jan  1 12:16:08 2021
Server: rtsp_demo
Content-Type: application/sdp
Content-Length: 479

v=0
o=- 0 0 IN IP4 0.0.0.0
s=rtsp_demo
t=0 0
a=control:rtsp://10.42.0.254:554/live/0
a=range:npt=0-
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
a=rtpmap:96 H265/90000
a=fmtp:96 sprop-vps=QAEMAf//AWAAAAMAgAAAAwAAAwCWvAk=;sprop-sps=QgEBAWAAAAMAgAAAAwAAAwCWoAEgIAURY2+7ymbgICAggAAAAwCAAAAMhA==;sprop-pps=RAHAcoaNQTZA
a=control:rtsp://10.42.0.254:554/live/0/track1
m=audio 0 RTP/AVP 97
c=IN IP4 0.0.0.0
a=rtpmap:97 PCMA/8000/2
a=control:rtsp://10.42.0.254:554/live/0/track2
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
SETUP rtsp://10.42.0.254:554/live/0/track1 RTSP/1.0
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
CSeq: 3
User-Agent: Lavf60.16.100

[DEBUG rtsp_demo.c:950:rtsp_handle_SETUP]
[INFO  rtsp_demo.c:894:rtsp_new_rtp_connection] new rtp over tcp for video ssrc:2234567c peer_addr:10.42.0.1 interleaved:0-1
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 3
Date: Fri Jan  1 12:16:08 2021
Session: 1234567A
Transport: RTP/AVP/TCP;ssrc=2234567C;interleaved=0-1
Server: rtsp_demo

[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
SETUP rtsp://10.42.0.254:554/live/0/track2 RTSP/1.0
Transport: RTP/AVP/TCP;unicast;interleaved=2-3
CSeq: 4
User-Agent: Lavf60.16.100
Session: 1234567A

[DEBUG rtsp_demo.c:950:rtsp_handle_SETUP]
[INFO  rtsp_demo.c:894:rtsp_new_rtp_connection] new rtp over tcp for audio ssrc:2234567d peer_addr:10.42.0.1 interleaved:2-3
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 4
Date: Fri Jan  1 12:16:08 2021
Session: 1234567A
Transport: RTP/AVP/TCP;ssrc=2234567D;interleaved=2-3
Server: rtsp_demo

[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
PLAY rtsp://10.42.0.254:554/live/0 RTSP/1.0
Range: npt=0.000-
CSeq: 5
User-Agent: Lavf60.16.100
Session: 1234567A

[DEBUG rtsp_demo.c:1037:rtsp_handle_PLAY]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 5
Date: Fri Jan  1 12:16:08 2021
Session: 1234567A
Server: rtsp_demo

[ntp.c][rkipc_ntp_update]:connect error
[DEBUG rtsp_msg.c:865:rtsp_msg_parse_from_array]
OPTIONS rtsp://10.42.0.254:554/live/0 RTSP/1.0
CSeq: 6
User-Agent: Lavf60.16.100
Session: 1234567A

[DEBUG rtsp_demo.c:725:rtsp_handle_OPTIONS]
[DEBUG rtsp_msg.c:998:rtsp_msg_build_to_array]
RTSP/1.0 200 OK
CSeq: 6
Date: Fri Jan  1 12:16:38 2021
Session: 1234567A
Public: OPTIONS, DESCRIBE, SETUP, PLAY, PAUSE, TEARDOWN
Server: rtsp_demo

2024/10/3

struct Node {
    std::string key;
    int value;
    std::vector<Node> children;

    REFLECT()       // Enable reflection for this type
};
REFLEC( ) 是:
define REFLECT() \
    friend struct reflect::DefaultResolver; \
    static reflect::TypeDescriptor_Struct Reflection; \
    static void initReflection(reflect::TypeDescriptor_Struct*);

所以是在 structure 中增加一個 static variable 和 一個function
Reflection,
initReflection()
然後還有宣告
/ Define Node's type descriptor
REFLECT_STRUCT_BEGIN(Node)
REFLECT_STRUCT_MEMBER(key)
REFLECT_STRUCT_MEMBER(value)
REFLECT_STRUCT_MEMBER(children)
REFLECT_STRUCT_END()
就是依序把Node struct 的 member 宣告一下。
這部份解開就是
    reflect::TypeDescriptor_Struct Node::Reflection{type::initReflection}; 
    void Node::initReflection(reflect::TypeDescriptor_Struct* typeDesc) { 
        using T = Node; 
        typeDesc->name = "Node"; 
        typeDesc->size = sizeof(Node); 
        typeDesc->members = {
        
            {"key",      offsetof(Node, key),      reflect::TypeResolver<std:tring>::get()},
            {"value",    offsetof(Node, value),    reflect::TypeResolver<int>::get()},
            {"children", offsetof(Node, children), reflect::TypeResolver<std:vector<Node>>::get()},
            
        };
    }
main( ) 在告完 Node 變數後,就呼叫:
   reflect::TypeDescriptor* typeDesc = reflect::TypeResolver<Node>::get();
看一下 reflect::TypeResolver<Node>::get*(),template 展開
struct TypeResolver {
    static TypeDescriptor* get() {
        return DefaultResolver::get<Node>();
    }
};
DefaultResolver:get 也是 template:
// This version is called if T has a static member named "Reflection":
    template <typename T, typename std::enable_if<IsReflected<T>::value, int>::type = 0>
    static TypeDescriptor* get() {
        return &T::Reflection;
    }

    // This version is called otherwise:
    template <typename T, typename std::enable_if<!IsReflected<T>::value, int>::type = 0>
    static TypeDescriptor* get() {
        return getPrimitiveDescriptor<T>();
    }
先解開
template <typename T, typename std::enable_if<IsReflected<T>::value, int>::type = 0>
用 std::enable_if 來區分要用那一個
std::enable_if<IsReflected<T>::value, int>::type = 0
enable_if 的 boolean 是 IsRlected<T>::value
IfReflected 是
    struct IsReflected {
        enum { value = (sizeof(func<T>(nullptr)) == sizeof(char)) };
    };
value 的值是 true or false:
(sizeof(func<T>(nullptr)) == sizeof(char)) 
func<T>(nullptr) 有兩個定義,由 T 沒有 member variable : Reflection 決定。Node 有,所以func 是..
template <typename T> static char func(decltype(&T::Reflection));
所以是sizeof(char),所以 value 是 true,也就是 IsReflected<Node>::value 是 true
配合 std::enable_if 用...
   template <typename T, typename std::enable_if<IsReflected<T>::value, int>::type = 0>
    static TypeDescriptor* get() {
        return &T::Reflection;
    }
所以是main( ) 中呼叫 :: get( ) 會回傳,Node::Reflection

之後 typeDesc->dump(&node);
就是 static reflect::TypeDescriptor_Struct 的 dump() :
    virtual void dump(const void* obj, int indentLevel) const override {
        std::cout << name << " {" << std::endl;
        for (const Member& member : members) {
            std::cout << std::string(4 * (indentLevel + 1), ' ') << member.name << " = ";
            member.type->dump((char*) obj + member.offset, indentLevel + 1);
            std::cout << std::endl;
        }
        std::cout << std::string(4 * indentLevel, ' ') << "}";
    }

2024/9/22

protobuf 提供了 structure 到 binary 的讀/寫 定義方式。
在 abc.proto 中定義了 structure.
再用 protoc 產生 C or python code,就會有 serializetostring 和 parsefromstring 兩個 讀/寫 檔的 function.

onnx 就是利用 protobuf 來做onnx

2024/9/20

RV1106 luckfox pico build and download

rv1106 的燒錄工具是 Soctoolkit,不是 Rkdevtool.
Soctoolkit 的 partition layout 是在 env.image.
類似 Rkdevtool 的parmeter.txt

以 Luckfox Pico為例,要進入 bootrom (MASKROM) 的方式是按著 boot 按鍵開機。
因為 Type C 兼顧供電與通訊,所以就是按著boot 鍵,插入 usb,放掉 boot 鍵。
這樣就會進入 maskrom,然後 Soctoolkit 就會顯示 USB : MASKROM 版本

之後在 search path 選到 sdk build 玩的 image 目錄 (例如 ~\luckfox-pico\IMAGE\SPI_NAND_RV1106G-LUCKFOX-PICO-PRO-MAX.DTS_20240920.1158_RELEASE_TEST\IMAGES)
他就會自己找到 env.image, load 完後,所有 partition 和 img file 都會列出來。

2024/9/6

新 android 的一些 build 動作改變

上次做Android 是 android 6 還是 8,現在已經是14 了。
紀錄一下現在的樣子。

showcommands

已經不用 showcommands,反而是會把 build log 放到 out/verbose.log.X.gz

partitions

用 device-mapper 而不是直接 mount。
所以 mount 看到的都是 /dev/block/dm-0,1,...

另外,有包含很多 partition 的 super partition
對應 super.img 的工具有:
  • lpmake
  • simg2img
  • lpunpack

2024/9/5

test gdb step into virtual function

#include <iostream>
#include <cstdlib>
#include <ctime>

class Base {
public:
    virtual void show() {
        std::cout << "Base class show function" << std::endl;
    }
    virtual ~Base() = default;
};

class Derived1 : public Base {
public:
    void show() override {
        std::cout << "Derived1 class show function" << std::endl;
    }
};

class Derived2 : public Base {
public:
    void show() override {
        std::cout << "Derived2 class show function" << std::endl;
    }
};

void callShow(Base* obj) {
    obj->show();
}

int main() {
    std::srand(std::time(0)); // 設定亂數種子
    Base* b;

    if (std::rand() % 2 == 0) {
        b = new Derived1();
    } else {
        b = new Derived2();
    }

    callShow(b);
    delete b;
    return 0;
}

2024/9/2

gitlab api , set default branch

ref:

gitlab ce 的rest api 的url 是
http://gitlab.loyaltek.com/api/v4/
之後就是 rest api 的 api resource,例如 projects, groups, users..

gitlab 的 rest api resource 頁面,以runners 為例。
GET /runners/:id/jobs
就是說:
  • http method : GET
  • uri endpoint: /runners/:id/jobs
所以用 curl 就是:
curl -X GET -H "PRIVATE-TOKEN=XXXXX" -url "http://gitlab.loyal.com/api/v4/runners/:id/jobs"
其中 :id 是指 gitlab 中的 project。

gitlab 的所有project,都有一個 id,例如 MISC/testwebapi2:


上面例子的 :id 就是改成 3756。

:id 其實有兩種表示法,一種是剛剛說的 unique id。
另一種就是 namespaced path encoding.

以上面 MISC/testwebapi2 為例,要是完整寫進 url 中, "/" 就會跟後面的 /jobs 混淆。
所以 project 的 path 中的 "/" 要改成 "%2F" : MISC%2Ftestwebapi2

也就是說,上面的例子, :id 可以是 3756,也可以是 MISC%2Ftestwebapi2


request header 的 token 就去 gitlab 的頁面create 一個。
可以在user 的頁面create,也可以在 project, group 的setting create,每個地方 create 的 token,應用範圍不一樣。

有關 set default branch...

第一篇是說:
DEFAULT_BRANCH="develop"
sleep 5
$(curl -sS -X $METHOD \
    -H "PRIVATE-TOKEN: $GITLAB_TOKEN" \
    --url "$GITLAB_URL/projects/$1" \
    --data "default_branch=$DEFAULT_BRANCH")

例如,create new project in subgroup:
curl --request POST --header "PRIVATE-TOKEN: glpat-FtpBssK5S5U6UMdkmcvL" \
 --data "name=testwebapi2" \
 --data "namespace_id=197" \
 "http://gitlab.loyaltek.com/api/v4/projects"
這個 namespace_id 就是 subgroup 的 id,在 gitlab 的 group 頁面,會有 id: 197

project 指定可以用 id (gitlab 的subgroup, project 都有 id)
也可以用 namespace (就像是 path)
不過 path 的 '\' 要改成 %2F

所以 /misc/testwebapi2,project id 是 3756,要 create new branch 可以:
curl --request POST --header "PRIVATE-TOKEN: glpat-FtpBssK5S5U6UMdkmcvL" \
 --url "http://gitlab.loyaltek.com/api/v4/projects/3756/repository/branches?branch=newbranch&ref=master"
 
或是
curl --request POST --header "PRIVATE-TOKEN: glpat-FtpBssK5S5U6UMdkmcvL" \
 --url "http://gitlab.loyaltek.com/api/v4/projects/MISC%2Ftestwebapi2/repository/branches?branch=newbranch2&ref=master"
也就是 url中,projects 後的 id 3756 改成 MISC/testwebapi2,因為要把 "/" 改掉以免線後麵的 repository 混搖,所以規定改成 %2F



要設定 default_branch 的話,就是參考 edit project 的範例:
API 是:
PUT /projects/:id
  • METHOD : PUT
  • resource: projects
project attrib 有 default_branch, value type 是 string。
id 可以用 project id,或是用 pathname (/ 改 %2F)
所以,設定 MISC/testwebapi2 的 defultbranch 是 newbranch2:
curl --request PUT --header "PRIVATE-TOKEN: glpat-FtpBssK5S5U6UMdkmcvL" \
 --url "http://gitlab.loyaltek.com/api/v4/projects/MISC%2Ftestwebapi2" \
 --data "default_branch=newbranch"