반응형

Smart TV

필자는 중소기업의 가성비 스마트 티비를 사용한다.
처음에는 안드로이드 TV 라서 모든 OTT 서비스를 사용하고 4K 티비를 저렴한 가격에 쓸 수 있다는 것에 엄청난 만족을 하며 사용하고 있었다.
현재는 모든 컨텐츠의 소비가 Streaming Service 기반으로 되어 있어서 아무 거리낌 없이 사용하고 있지만, 초반에는 시작할 때나 이동할때 Loading 표시가 그렇게 거리낌이 있을 수가 없었지만 지금은 그려려니 하고 쓰는데 요즘 Android가 무거워진건지 앱들이 기능들의 개선으로 무거워 진건지 예전처럼 빠릿 빠릿 한거 같지도 않고, 유투브 볼때도 조금 건너뛸때마다 Loading이 걸리는게 조금씩 짜증이 났다.

PS5

필자는 학생때가 지난 이후로 게임은 단순히 성능 평가 정도로만 하고 예전처럼 의욕이 없어서 게임기를 사본적이 없다.
그러다가 동생에게 PS5를 기회가 될 일이 있어서 뺏어서 쓰고 있는데, 갓오브워 같은 명작만 1주에 한두번 정도 하다가 한달에 한두번 킬랑 말랑 한 상태로 여태까지 쓰다가 요즘 오공이라는 게임의 화려함에 빠져 구매하고 가끔 플레이를 하고 있다.
그러다가 회사 동료였던 후배가 SONY에서 근무할 때에 PlayStation 개발자였는데, 그 때에 사놓은 PS를 넷플릭스나 유투브 보는 용도로만 사용한다는 얘기를 했던게 기억이 나서 몇년만에 PS5를 키고 YouTube, Netflix, DisneyPlus 등의 앱을 설치를 해보았는데, 이게 엄청 빠른것이다!.
티비로 보면 화면속 화질이 4k가 될때까지 기다려야 했는데 바로 4k로 뜨고, 찾기등을 해도 바로 바로 결과가 나오고 심지어 음성인식도 훨씬 잘되는 것 같아보여서 PS5로 티비를 봐야겠다 하면서 "여태까지 내가 왜 그냥 티비로 참으며 쓰고 있었지?" 하고 생각하고 있었는데, 쓰다보니 또 사람이란게 불편해지는게 생기는데 그건 바로 컨트롤러 였다.
게임 컨트롤러로 리모컨 대신 사용하자니 이거 또 여간 불편한게 아니다.
티비 리모컨 따로 써서 티비 컨트롤 하다가, 앱을 사용할 때에는 PS5 컨트롤러를 사용하는데 이거 또 조이스틱 스치기라도 하면 위치찾기로 멈춰있는다. 뭐 그래도 이게 좋으니까 써야지 하다가, 지난 후배가 했던 말이 생각나서, 리모컨이 있지 않을까 생각되서 이리 저리 검색해보니 PS5용 리모컨이 있다는 것을 알게 되었다.

PS5 리모컨

처음에는 Aliexpress에는 뭐 어떻게든 호환되게 해서 파니까 라는 생각에 Aliexpress에서 검색해서 구매를 했는데, 한국에서도 판매를 하는 것 같다. 필자가 구매한 곳도 국내 판매업자가 등록한거라서 사실 다를바가 없는데 Aliexpress에서 자체적인 할인등으로 인해서 약 15% 정도는 더 저렴하게 산 것 같다.

아무 생각없이 가품을 생각하고 주문했는데 정품이 왔다.

장점

간단하게 사용해보고 장점을 열거한다.

  1. 컨트롤러를 사용할 필요가 전혀 없다.
  2. 가볍고 필요한 버튼만 있어서 조그맣고 디자인도 이쁘다.
  3. TV기능도 사용할 수 있다(다만 모니터에 연결할 경우 안된다고 알고 있다. HDMI로 연결된 특정할 수 없는 브랜드도 사용이 가능한 것 같다. HDMI로 TV 동작에 필요한 명령도 날릴 수 있는 것 같다. 현재 전원 ON/OFF, 소리 등 티비 리모컨은 당장 사용을 안해도 될것 같다)
  4. Netflix, Youtube, Disney+ 버튼이 있다. 공교롭게도 제일 활용을 잘하는 세가지 서비스다.
  5. 컨트롤러로 PS 5의 전원을 켜거나 잠에서 깨울 경우 미디어 카테고리로 이동을 해야하는데 리모컨으로 동작시킬 경우 바로 미디어로 켜진다.

단점

  1. 충전식이 아닌 배터리 교환식이다. 근데 리모컨이 그렇듯 자주 배터리가 떨어질 일이 없으니 큰 문제가 되지 않는 것 같다.

아직 생각나는 단점이 없다. 사용을 해보다가 불편한 점이 있으면 추가하도록 하겠다.

반응형
반응형

Client 에서 Key 생성

$ cd ${HOME}
$ ssh-keygen -t rsa -P ""

Key 등록

$ ssh-copy-id -i ${HOME}/.ssh/rd_rsa.pub <USER>@<IP>

Test

$ ssh <USER>@<IP>
반응형
반응형

docker-container-runtime의 설치가 되어 있는지 확인이 필요함

$ dpkg -l | grep docker-container-runtime

없을 경우 아래와 같이 패키지를 설치 가능한지 확인함

$ sudo apt search docker-container-runtime

설치 가능할 경우 설치

$ sudo apt install docker-container-runtime

docker restart

$ sudo systemctl restart docker
반응형
반응형

비엔나에서 발레를 보려니 가격이 만만치 않다.

포기를 하던차에 지인이 프라하 국립극장에서 보면 가격도 부담없고, 퀄리티도 좋다 그래서 보니 정말 메리트 있어서 예약을 하려고 보니 좌석이 영어도 아닌것이 너무 정신없고 정보가 없어서 선택을 하기 쉽지 않다.

이럴때 chatgpt를 잘 활용하니 정보가 깔끔하게 나와서 저장해본다.

프라하에서 발레를 감상할 수 있는 대표적인 공연장은 **프라하 국립극장 (Národní divadlo)**와 **에스테이트 극장 (Stavovské divadlo)**입니다. 두 극장 모두 아름다운 내부와 훌륭한 음향, 시야를 제공하지만 좌석별로 관람 경험이 다를 수 있습니다. 좌석 선택에 대한 자세한 정보를 제공해 드리겠습니다.
1. 오케스트라 석 (Orchestra/Stalls)
위치: 무대와 같은 층에 위치한 좌석으로, 무대와 가장 가까운 위치에 있습니다.특징 및 장점:배우들의 표정과 움직임을 자세히 볼 수 있습니다.음향이 직접적으로 전달되어 생동감 있는 사운드를 즐길 수 있습니다.발레에서 춤의 디테일을 중점적으로 감상하고 싶은 경우 좋습니다.추천 열:앞쪽에서는 3~6열이 가장 좋습니다. 첫 두 열은 목을 많이 젖혀야 하며, 7열 이후로는 시야가 조금 더 제한될 수 있습니다.
2. 박스 석 (Boxes)
위치: 극장의 양옆과 뒤쪽 벽에 위치한 개인용 박스 석.특징 및 장점:개인적이고 프라이빗한 경험을 제공합니다.옆쪽 박스는 무대 측면을 약간 비스듬하게 보게 되지만, 박스의 위치에 따라 무대 전체를 잘 볼 수 있습니다.고급스러운 분위기에서 공연을 감상할 수 있어 특별한 경험을 원할 때 좋습니다.추천 위치:중앙에 위치한 박스나, 무대에 가까운 앞쪽 박스가 더 좋은 시야를 제공합니다.중간 박스에서는 앞쪽 좌석이 더 나은 시야를 보장합니다.
3. 발코니 석 (Balcony)
위치: 극장의 2층이나 3층에 위치한 좌석.특징 및 장점:무대를 전체적으로 조망할 수 있어 발레의 대규모 군무나 무대 전체의 구성을 감상하기에 좋습니다.소리가 고르게 퍼져 음향적으로도 좋은 경험을 할 수 있습니다.상층 발코니는 가격이 더 저렴해 가성비가 좋습니다.추천 열:1층 발코니의 1~2열이 시야와 음향 면에서 최적입니다.2층 발코니의 경우도 1열은 훌륭한 선택입니다.
4. 갤러리 석 (Gallery)
위치: 가장 높은 층에 위치한 좌석.특징 및 장점:전체적인 무대 구성을 감상할 수 있지만, 무대와의 거리가 가장 멉니다.예산이 제한된 경우나, 전체적인 구성을 보려는 관객에게 적합합니다.추천 열:갤러리에서 가장 앞쪽 열이 가장 좋으며, 시야가 좀 더 넓게 확보됩니다.

결론
프라하에서 발레를 감상할 때 최고의 좌석은 개인의 선호에 따라 달라질 수 있습니다. 무대 가까이에서 세밀한 움직임을 보고 싶다면 오케스트라 석이 좋고, 전체적인 구도와 대규모 군무를 선호한다면 발코니나 갤러리 석이 좋습니다. 특별한 경험을 원한다면 박스 석이 적합합니다. 일반적으로 오케스트라 석의 36열, 발코니의 12열이 가장 추천됩니다.

 

추가 ====================

발레 공연 후기

https://onestepcloser.tistory.com/254

 

[프라하] 프라하 국립극장에서 발레 공연 후기

프라하 국립 극장(Národní divadlo)프라하와 비엔나를 비교를 많이 하는데, 사실 양쪽에서 모두 본 입장에서 예술쪽에 조예가 깊지 않은 이상 비엔나에서 예술 공연을 보는 가격이 부담이 된다면,

onestepcloser.tistory.com

 

반응형
반응형

Pad negotiation

Gstremaer에서 개발하는데 잘 모르고 개발이 잘 안되는 가장 큰 부분이 Pad Negotiation이다. 대충 Printf로 찍어보며 개발이 안된다. 원리를 이해를 해야 할거 같아서 페이지에서 정리할 겸 번역하며 정리를 해보았다.

Negotiation

Basic Rules

These simple rules must be followed:

  1. downstream suggests formats
  2. upstream decides on format

4 Queris/events used in negotiation

  1. GST_QUERY_CAPS: get possible formats
  2. GST_QUERY_ACCEPT_CAPS: check if format is possible
  3. GST_EVENT_CAPS: configure format (downstream)
  4. GST_EVENT_RECONFIGURE: inform upstream of possibly new caps

Query

Pad query는 GstCaps로 이용하며 재귀적으로 동작할 수 있음

  • filter (in) GST_TYPE_CAPS (default NULL): - a GstCaps to filter the results against
  • caps (out) GST_TYPE_CAPS (default NULL): - the result caps

Pad는 peer pad에 주어진 caps가 지원되는지 물어볼 수 잇따. 이것은 ACCEPT_CAPS query를 통해 이루어진다. 이때 caps는 반드시 fixed여야 한다. ACCEPT_CAPS는 Recursive로 동작하지 않는다. 단순히 accept되어지면 TRUE를 return한다.

  • caps (in) GST_TYPE_CAPS: - a GstCaps to check, must be fixed
  • result (out) G_TYPE_BOOLEAN (default FALSE): - TRUE if the caps are accepted

Event

mediaformat 이 negotiated 상태가 되면 peer element는 CAPS event로 notified된다. 이떄 caps는 반드시 fixed여야 한다.
caps GST_TYPE_CAPS: - the negotiated GstCaps, must be fixed

Operation

Gstreamer는 두가지 scheduling mode를 지원하며 이것은 push mode와 pull mode이다 두가지는 목표가 다른 서로 다른 메커니즘으로 동작한다.

Push-mode negotiation

Push-mode negotiation은 element가 buffer를 push하고 format을 결정하기를 원할때 이루어지며, 이는 downstream negotiation으로 불리는데 이는 upstream element는 downstream element에 대하여 format을 결정하기 때문이고 이것은 일반적인 케이스이다.

Negotiation은 또한 downstream element가 upstream element로 부터 다른 data format을 받기를 원할때도 이루어진다.

Basic negotiation은 아래와 같다.

  • GstCaps는 buffer의 contents에 대한 describe의 event를 push하기 이전에 참조 카운트를 한다.
  • Element는 이어질 Buffer의 processing이전에 CAPS event로서 새로운 format을 전달받기 위하여 스스로 reconfigure되어야 한다. 만약 data type이 not acceptable일 경우, element는 event 를 거절(refuse)해야 한다. Element는 chain function에서 buffer 유입에 대해서 GST_FLOW_NOT_NEGOTIATED를 return해야 한다.
  • Downstream element는 upstream 에 대해서 RECONFIGURE event를 보냄으로, stream format이 변경에 대해 요청을 할 수 있다. Upstream element은 RECONFIGURE event를 수신하면 new format에 대해서 다시 negotitation을 수행할 것이다.

아래는 source pad의 negotiation을 시작하는 일반적인 Flow이다.

            src              sink
             |                 |
             |  querycaps?     |
             |---------------->|
             |     caps        |
select caps  |< - - - - - - - -|
from the     |                 |
candidates   |                 |
             |                 |-.
             |  accepts?       | |
 type A      |---------------->| | optional
             |      yes        | |
             |< - - - - - - - -| |
             |                 |-'
             |  send_event()   |
send CAPS    |---------------->| Receive type A, reconfigure to
event A      |                 | process type A.
             |                 |
             |  push           |
push buffer  |---------------->| Process buffer of type A
             |                 |

아래는 구현에 대한 Pseudo code 예제이다.

[element wants to create a buffer]
if not format
  # see what we can do
  ourcaps = gst_pad_query_caps (srcpad)
  # see what the peer can do filtered against our caps
  candidates = gst_pad_peer_query_caps (srcpad, ourcaps)

  foreach candidate in candidates
    # make sure the caps is fixed
    fixedcaps = gst_pad_fixate_caps (srcpad, candidate)

    # see if the peer accepts it
    if gst_pad_peer_accept_caps (srcpad, fixedcaps)
      # store the caps as the negotiated caps, this will
      # call the setcaps function on the pad
      gst_pad_push_event (srcpad, gst_event_new_caps (fixedcaps))
      break
    endif
  done
endif

Negotiate allocator/buffer pool with the ALLOCATION query

    buffer = gst_buffer_new_allocate (NULL, size, 0);
    # fill buffer and push

아래는 sink pad의 renegotiation을 시작하는 일반적인 Flow이다.

            src              sink
             |                 |
             |  accepts?       |
             |<----------------| type B
             |      yes        |
             |- - - - - - - - >|-.
             |                 | | suggest B caps next
             |                 |<'
             |                 |
             |   push_event()  |
 mark      .-|<----------------| send RECONFIGURE event
renegotiate| |                 |
           '>|                 |
             |  querycaps()    |
renegotiate  |---------------->|
             |  suggest B      |
             |< - - - - - - - -|
             |                 |
             |  send_event()   |
send CAPS    |---------------->| Receive type B, reconfigure to
event B      |                 | process type B.
             |                 |
             |  push           |
push buffer  |---------------->| Process buffer of type B
             |                 |

Pull-mode negotiation

Pull mode Pipeline 은 push mode와 negotiation 요구사항이 다름. Push mode는 아래의 두가지 Use cases에 최적화 되어 있음

  • Media file Playback에 대해서 어떤 정보가 전달되어야 하는 고나점에서의 decoder, demuxer의 관점
  • Live source recording에 대해서 source element 다음에 capsfilter를 추가하는데 익숙함, 그러므로 caps information flow는 Pipeline의 sink들을 향해서 source의 잠재적인 caps를 통해 user에 의해 결정됨.

그에 반해 Pull mode는 아래의 전형적인 use case들이 있음

  • RTP와 같은 손실이 있는 Source를 재생할 떄에 Latency에 대한 추가 정보로 품질을 향상 시킬 수가 있음.
  • 오디오 합성에서, 오디오 API는 필요한 샘플 수만 생성하도록 조정되며, 일반적으로 하드웨어 인터럽트에 의해 구동되어 DMA 버퍼나 Jack[0] 포트 버퍼를 채우는 방식으로 작동함.
  • 저지연 효과 처리를 위해, 필터는 데이터를 링 버퍼에서 싱크로 전송할 때 적용되어야 하며, 미리 적용되지 않아야 함. 예를 들어, alsasink의 내부 링버퍼 스레드를 푸시 모드에서 사용하는 대신, wavsrc ! volume ! alsasink와 같은 구성 대신 wavsrc ! audioringbuffer ! volume ! alsasink로 사운드 카드 쓰기 스레드 내에 볼륨을 배치하는 방식이 있음.

Pull mode에서 문제는 sink가 gst_pad_pull_range()를 통해 몇 바이트를 가져와야 하는지 알기 위해 format을 알아야 한다는 점이 있음. 이는 데이터를 가져오기 전에 sink가 negotiation을 시작하여 format을 결정해야 함을 의미함.

RTP 및 저지연 재생은 일반적인 재생과 유사하게 정보가 downstream으로 흐름.

오디오 합성에서는 정보가 가장 많은 부분이 sink 쪽에 있으며, 이때 caps는 완전히 지정되지 않고 사용자가 샘플 속도 등을 선택해야 합니다. 이 과정은 gstreamer 외부에서나 capsfilter를 통해 수행될 수 있음.

싱크가 소스의 입력을 필요로 하는 경우 협상 단계가 필요하며, 풀 모드의 저지연 특성상 풀링 스레드 내에서 협상을 피해야 함.

Pull thread는 보통 PAUSED에서 PLAYING으로 상태가 변경될 때 시작되므로, 이 상태 변경 전에 negotiation을 완료해야 함.

따라서 caps negotiation은 SCHEDULING Query가 성공한 후, pulling thread가 시작되기 전에 수행해야 함.

Machanism

Sink는 SCHEDULING query를 통해 Upstream element들이 Pull based scheduing을 지원하는지 확인함.

Sink는 자신의 sink pad와 연결된 src pad에서 gst_pad_query_caps()의 결과를 교차하여 Negotiation 과정을 시작합니다. 간단한 Passthrough의 경우, 피어 패드의 caps through는 모든 sink pad에 대해 get_allowed_caps()를 호출한 결과의 교집합을 반환해야 합니다. 이를 통해 sink element는 Pipeline 전체의 기능을 파악합니다.

필요한 경우 sink element는 결과 caps를 고정하여 flow caps를 생성합니다. 이 시점부터 sink pad의 caps query는 이 fixed caps만 반환하며, Upstream element들은 이 형식만 생성할 수 있게 됩니다.

sink element가 sink pad에 caps를 설정하지 못했다면, 버스에 오류 메시지를 게시하여 Negotiation이 불가능했음을 알립니다.

Negotiation이 성공하면, sink pad와 모든 내부적으로 연결된 Upstream Pad가 Pull mode로 활성화됩니다. 일반적으로 이 작업은 Downstream element에서 Negotiation을 trigger하여, 이제 Sink pad의 최종 Fixed caps와 Negotiation하게 됩니다.

이 단계가 완료된 후, Sink element는 상태 변경 함수에서 ASYNC를 반환합니다. 첫 번째 버퍼가 Sink에 도착하면 상태가 PAUSED로 전환됩니다. 이는 Sink에서 ASYNC 반환 값을 기대하는 application에 일관된 API를 제공하기 위해 필요하며, Polling thread의 Context 외부에서 나머지 negotiation을 수행할 수 있도록 합니다."

Pattern

Negotiation에서 3가지 패턴을 구분할 수 있음:

  1. 고정(Fixed): 출력 형식을 선택할 수 없음.
    • Stream에 인코딩된 caps
    • 비디오/오디오 decoder가 일반적으로 사용
    • gst_pad_use_fixed_caps()를 사용
  2. 변환(Transform): CAPS가 수정되지 않음(passthrough)
    • 요소 속성에 따라 CAPS 변환 가능
    • 고정된 caps가 고정된 caps로 변환
    • 예: videobox
  3. 동적(Dynamic): 출력 형식을 선택할 수 있음
    • 변환 요소
    • Downstream caps에 따라 다르며, CAPS 쿼리 필요
    • 일반적으로 동일한 변환을 선호
    • 고정된 caps가 고정되지 않은 caps로 변환 가능

출처

https://gstreamer.freedesktop.org/documentation/additional/design/negotiation.html?gi-language=c
반응형

+ Recent posts