<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Ivan Kuten</title>
    <description>The latest articles on Forem by Ivan Kuten (@ivan_kuten).</description>
    <link>https://forem.com/ivan_kuten</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F442974%2F481a6895-b36d-49ab-8caa-afab980e7773.jpg</url>
      <title>Forem: Ivan Kuten</title>
      <link>https://forem.com/ivan_kuten</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ivan_kuten"/>
    <language>en</language>
    <item>
      <title>Making React Work on Smart TVs: Behind the Scenes of the Sportworld App</title>
      <dc:creator>Ivan Kuten</dc:creator>
      <pubDate>Thu, 30 Oct 2025 14:53:02 +0000</pubDate>
      <link>https://forem.com/ivan_kuten/making-react-work-on-smart-tvs-behind-the-scenes-of-the-sportworld-app-2ahi</link>
      <guid>https://forem.com/ivan_kuten/making-react-work-on-smart-tvs-behind-the-scenes-of-the-sportworld-app-2ahi</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Building apps for Smart TVs with React is nothing like the web. Here’s how we made a sports streaming platform stay stable and responsive on Samsung TVs — even with memory limits, performance quirks, and old hardware. &lt;/p&gt;

&lt;p&gt;When we were asked to bring a sports streaming app to millions of Samsung Smart TVs — including models as old as 2017 — we knew performance and compatibility would be our biggest hurdles.  &lt;/p&gt;

&lt;p&gt;And yes, those hurdles were real. Even after months of tuning, older Samsung models still push the limits — memory leaks, dropped frames, unpredictable behavior. But the app holds up. It recovers, it doesn’t crash, and that’s a win when you’re running React on a TV from 2017. &lt;/p&gt;

&lt;h2&gt;
  
  
  About the Project
&lt;/h2&gt;

&lt;p&gt;Our client, NativeWaves, delivers interactive streaming experiences for sports and entertainment. Together with B1 SmartTV, they launched Sportworld, a sports hub preinstalled on Samsung TVs in Germany. &lt;/p&gt;

&lt;p&gt;Our task was to rebuild the app for Tizen OS, and make the product ready for future ports to WebOS and FireTV – while implementing new interactive features such as switching camera angles, jumping into live replays, and exploring on-demand content.  &lt;/p&gt;

&lt;p&gt;Eventually, the platform became part of a partnership with the German Bundesliga — the country’s top professional football league — giving fans access to live multi-angle match experiences. &lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering Challenge
&lt;/h2&gt;

&lt;p&gt;Developing for Smart TVs is a different world. We had to make sure the app: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs smoothly even on older Samsung devices (2017+ models) with limited memory and CPU power. &lt;/li&gt;
&lt;li&gt;Provides a premium, lag-free video experience (live and on-demand). &lt;/li&gt;
&lt;li&gt;Handles multiple interactive features — without breaking UX. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On top of that, we needed a modular architecture that would make porting to other TV and mobile platforms fast and predictable. &lt;/p&gt;

&lt;h2&gt;
  
  
  How We Tested and Profiled It
&lt;/h2&gt;

&lt;p&gt;Profiling React apps on Smart TVs turned out to be a challenge of its own. To get accurate performance data, we had to use older versions of Chrome — version 79 for 2018 TVs, and for 2016–2017 models even Chrome 56 on a separate old machine. &lt;/p&gt;

&lt;p&gt;Modern DevTools simply don’t show what’s really happening inside Tizen’s JavaScript engine. &lt;/p&gt;

&lt;p&gt;We also tried the emulators from Tizen Studio, but success was hit-or-miss. They only work if the host CPU supports hardware virtualization, and there’s no ARM build — which means no luck on modern Mac M1+ machines. &lt;/p&gt;

&lt;p&gt;In practice, debugging on real devices was the only reliable way to see how the app behaved. This experience shaped our approach: measure performance where it actually runs, not where it’s convenient. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9pf54h2vuem7v0j5xeo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9pf54h2vuem7v0j5xeo8.png" alt=" " width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack and Architecture
&lt;/h2&gt;

&lt;p&gt;We built the frontend with a lightweight and highly responsive setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;React.js, TypeScript 
Styled-components 
Zustand 
Webpack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Zustand state management turned out to be simpler and faster than Redux for our needs, while styled-components helped us dynamically theme different app sections (global and per-page themes). &lt;/p&gt;

&lt;p&gt;We also put special effort into keeping the bundle small and efficient — avoiding unnecessary re-renders and using lazy loading for heavy components like video players and analytics modules. &lt;/p&gt;

&lt;p&gt;The backend was provided by the client, with well-structured REST APIs documented via Swagger. This setup allowed our team to react quickly to API updates and maintain high development velocity. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmu9a2mgl1sl0gyboa8mv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmu9a2mgl1sl0gyboa8mv.png" alt=" " width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why React on Smart TVs Is Challenging
&lt;/h2&gt;

&lt;p&gt;Running React on Smart TVs isn’t a matter of framework — it’s a matter of physics. &lt;/p&gt;

&lt;p&gt;We didn’t choose React; it came with the project. Our job was to make it work inside the limits of Tizen and WebOS — where every render and memory allocation counts. &lt;/p&gt;

&lt;p&gt;Even mid-range TVs have less CPU and RAM than most phones. Their browser engines are outdated, garbage collection is slow, and firmware updates are unpredictable. That means even small things — image size, runtime CSS, a few extra listeners — can affect playback smoothness. &lt;/p&gt;

&lt;p&gt;We tuned what we could: cut bundle size, trimmed re-renders, and lazy-loaded heavy components. Locally, in the browser, performance looked great. On real TVs — still tight. The app stayed responsive and didn’t crash, but the margin for error was razor-thin. &lt;/p&gt;

&lt;h3&gt;
  
  
  What made it tricky
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Hardware ceilings.&lt;/strong&gt; &lt;br&gt;
Older Samsung models have minimal CPU and GPU power. React’s re-renders can easily cause dropped frames or sluggish navigation. We profiled the UI, flattened component trees, and stripped unnecessary animations to keep interactions predictable during live playback. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Outdated JavaScript engines.&lt;/strong&gt; &lt;br&gt;
Tizen and WebOS browsers don’t match modern Chromium. Some ECMAScript features behave differently, and bundle size directly affects startup time. We tested every polyfill and adjusted TypeScript output for backward compatibility. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Remote-only UX.&lt;/strong&gt; &lt;br&gt;
No touch, no cursor — just arrow keys and OK. We built our own focus management layer to make remote navigation feel instant and natural. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu9xu5bmd3u8m0q0f887.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu9xu5bmd3u8m0q0f887.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Video meets React.&lt;/strong&gt; &lt;br&gt;
Multiple streams (live, replay, VOD) run alongside the UI. To prevent freezes, we isolated video logic from React’s render cycle and throttled event updates. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Debugging in the dark.&lt;/strong&gt; &lt;br&gt;
Smart TV SDKs give little visibility. Deploying to devices takes minutes, not seconds. We built emulators and detailed logs to reproduce TV-specific issues locally. &lt;/p&gt;

&lt;p&gt;In the end, React on Smart TVs isn’t about libraries or syntax. It’s about patience and precision — squeezing stable performance from hardware that was never meant to run a modern frontend framework. &lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features We Implemented
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Live HLS streaming and VOD playback &lt;/li&gt;
&lt;li&gt;Event calendar and promoted highlights &lt;/li&gt;
&lt;li&gt;QR-based login and SSO integration via Plenigo &lt;/li&gt;
&lt;li&gt;Paid subscriptions and campaign support for new TV models &lt;/li&gt;
&lt;li&gt;Custom Google Analytics events for in-depth engagement tracking &lt;/li&gt;
&lt;li&gt;Support for deep links (jumping directly to a live match or replay) &lt;/li&gt;
&lt;li&gt;Optimized UI for remote control navigation (a major UX difference vs. mobile) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features turned Sportworld into a fully interactive second-screen experience — where fans can easily switch camera angles, follow replays, and explore on-demand content. &lt;/p&gt;

&lt;h3&gt;
  
  
  Portability Matters
&lt;/h3&gt;

&lt;p&gt;From the start, we structured the app with platform-agnostic modules and minimal dependencies on Tizen-specific APIs. &lt;/p&gt;

&lt;p&gt;That decision paid off later: when the client wanted to expand to WebOS and FireTV, we could reuse about 80% of the codebase with minimal adaptation. &lt;/p&gt;

&lt;p&gt;We also designed the architecture to support future integrations — from new sports to additional analytics providers — without rewriting core logic. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpoqd5i3qyjbqeiu14fzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpoqd5i3qyjbqeiu14fzc.png" alt=" " width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;React on Smart TVs is all about restraint.&lt;/strong&gt;&lt;br&gt;
Performance tuning matters more than adding libraries. Profiling tools and manual optimization saved us from micro-stutters on older models. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan for portability early.&lt;/strong&gt;&lt;br&gt;
Even if you start with a single platform, build with modular architecture. It makes future ports dramatically faster. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UX for TVs ≠ UX for mobile.&lt;/strong&gt;&lt;br&gt;
Designing for remote navigation and slower hardware requires a different mindset — focus on responsiveness and minimal animation complexity. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dedicated teams work.&lt;/strong&gt;&lt;br&gt;
Our setup — 3 engineers at start, scaling to 9 at peak — kept communication efficient and made delivery predictable for the client. &lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;The Sportworld app is now pre-installed on Samsung TVs in Germany and continues to evolve with new sports and interactive features. &lt;/p&gt;

&lt;p&gt;Also, we launched the WebOS version — built on the same core architecture. The only difference: it’s not pre-installed, but available as a downloadable app through LG’s content store. &lt;/p&gt;

&lt;p&gt;This step confirmed that our platform-agnostic setup works in practice, not just on paper. The same base now serves as a foundation for future ports to FireTV and other devices. &lt;/p&gt;




&lt;p&gt;I prepared this article together with the engineers from our dedicated team at Promwad, who built and optimized the app. If you’d like to see the demo video and more details from the project, check out &lt;a href="https://promwad.com/case-studies/sportworld-smarttv-app" rel="noopener noreferrer"&gt;the full Sportworld Smart TV App Case&lt;/a&gt; on our website. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>showdev</category>
      <category>react</category>
    </item>
    <item>
      <title>Linux and CPSS Assembly on Marvell Board with Prestera DX Switch</title>
      <dc:creator>Ivan Kuten</dc:creator>
      <pubDate>Mon, 04 Oct 2021 12:00:34 +0000</pubDate>
      <link>https://forem.com/ivan_kuten/linux-and-cpss-assembly-on-marvell-board-with-prestera-dx-switch-1agg</link>
      <guid>https://forem.com/ivan_kuten/linux-and-cpss-assembly-on-marvell-board-with-prestera-dx-switch-1agg</guid>
      <description>&lt;p&gt;We've prepared a step-by-step guide for assembling and launching reference firmware with CPSS on the Marvell RD-AC3X-48G4X2XL-A board. This board serves for &lt;a href="http://promwad.com/solutions/telecom/network-switches?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=cpss" rel="noopener noreferrer"&gt;managed switches&lt;/a&gt; with up to 48 ports design and debugging. What makes it a perfect fit for an engineer? It has a Marvell Prestera DX 98DX3257 switch with a powerful Prestera SoC family on board. Besides, Prestera DX Ethernet switches enable 5G at the industry's lowest requirements for power and space. &lt;/p&gt;

&lt;p&gt;As for CPSS, it is the basic software layer for Marvell Prestera hardware. CPSS stands forCore Prestera Software Suite. Open Compute Project uses CPSS as a part of the SONiC open network operating system. This OS extends data center functions in complex systems, such as intelligent data storage and machine learning. &lt;/p&gt;

&lt;p&gt;Moreover, CPSS high-level API helps developers leverage features of Marvell Packet Processor without in-depth knowledge of Prestera chipset registers and tables.&lt;/p&gt;

&lt;p&gt;CPSS locates in the user environment. It has several functions that require kernel-specific support:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interrupts:&lt;/strong&gt; a dedicated kernel module for forwarding Packet Processor interrupts to the CPSS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;To-and-fro CPU packet:&lt;/strong&gt; another kernel module for forwarding packets between the PCIe interface to dedicated SDMA memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That API allows complete configuration of the Prestera-based switch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhetr9u4sr9q9w5nznzbz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhetr9u4sr9q9w5nznzbz.png" alt="Marvell RD-AC3X-48G4X2XL-A board components" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our board already has a u-boot. It is loaded into the device nand-memory on the vendor side. &lt;/p&gt;

&lt;p&gt;Before following the steps in our guide, please, create an account on &lt;a href="https://www.marvell.com/portal" rel="noopener noreferrer"&gt;the Marvell portal&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Create a working directory
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;mkdir ~/marvell &amp;amp;&amp;amp; cd marvell&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Below you’ll find all the components you need to download and unpack in the ~/marvell directory (~/marvell). All the paths in the guide are relative to it. &lt;/p&gt;

&lt;p&gt;Let's start from the Products section of the Marvell portal:&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Download the toolchain (compiler, etc.) to build the kernel and cpss-application
&lt;/h2&gt;

&lt;p&gt;1.1 Go to &lt;a href="https://www.marvell.com/portal" rel="noopener noreferrer"&gt;the Marvell portal&lt;/a&gt; and select Products in the top center.&lt;/p&gt;

&lt;p&gt;1.2 Follow Tools→Marvell GNU Tools→MGCC-5→201511 on the left in the menu.&lt;/p&gt;

&lt;p&gt;1.3 Select Toolkit in the window on the right and download the necessary toolchain. At the time of this guide preparation this is armv7 marvell linux gnueabihf hard 5.2.1 x86_64 20160301.tar.xz.&lt;/p&gt;

&lt;p&gt;1.4 Unpack the archive to the working directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Download the Marvell assembly system with CPSS sources
&lt;/h2&gt;

&lt;p&gt;2.1 In the same Products section on the Marvell portal, select Switching→Software→CPSS-DXCH→4.2.2020.3 from the menu on the left.&lt;/p&gt;

&lt;p&gt;2.2 Click on the window on the right side of Base SDK and download CPSS 4.2.2020.3 release – GIT Source.&lt;/p&gt;

&lt;p&gt;2.3 Unpack the archive into the working directory.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Download instructions for assembling and using the Linux Marvell and CPSS image
&lt;/h2&gt;

&lt;p&gt;3.1 Again from the menu on the left, in the Products section, select Switching→Software→cpss→4.2.2020.3.&lt;/p&gt;

&lt;p&gt;3.2 Click the User Guide in the window on the right and download PSDK PIPE 4.2.2020.3 Release – User Guide.&lt;/p&gt;

&lt;p&gt;3.3 User Guide is a set of html-pages for browsers. To view it, unzip the archive and open the page in the root – PSDK_home.html.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Clone the Linux-Marvell kernel from Marvell Github and configure it
&lt;/h2&gt;

&lt;p&gt;4.1 git clone &lt;a href="https://github.com/MarvellEmbeddedProcessors/linux-marvell.git" rel="noopener noreferrer"&gt;https://github.com/MarvellEmbeddedProcessors/linux-marvell.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4.2 &lt;code&gt;mv ./linux-marvell ./cpss_release_git_CPSS_4.2_2020_03_018/kernel&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Please note that the kernel must be located near the sources of cpss. Its name must be kernel.&lt;/p&gt;

&lt;p&gt;4.3 &lt;code&gt;cd ./cpss_release_git_CPSS_4.2_2020_03_018/kernel&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;4.4 &lt;code&gt;git checkout remotes/origin/linux-4.4.52-armada-17.10&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;4.5 export ARCH=arm &amp;amp;&amp;amp; make mvebu_v7_lsp_defconfig&lt;/p&gt;

&lt;p&gt;Next, enable RAM disk support in the kernel. There are two ways to do this:&lt;/p&gt;

&lt;p&gt;– via make menuconfig &lt;/p&gt;

&lt;p&gt;– or write the following code in your .config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONFIG_BLK_DEV_RAM=y

CONFIG_BLK_DEV_RAM_COUNT=2 (maximum possible number of RAMs)

CONFIG_BLK_DEV_RAM_SIZE=524288 (the maximum size of a RAM disk in kb that the kernel can support; 524288 is 512 mb)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Configure the desktop environment
&lt;/h2&gt;

&lt;p&gt;Refer to the User Guide from Step 3 for the configuration process.&lt;/p&gt;

&lt;p&gt;5.1 &lt;code&gt;cd PSDK_PIPE_4.2.2020.3_UserGuide&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;5.2 Open PSDK_home.html.&lt;/p&gt;

&lt;p&gt;5.3 CPSS User Guide on the left.&lt;/p&gt;

&lt;p&gt;5.4 Building CPSS → Building CPSS in Linux → Installing the Development Environment — on the left. &lt;/p&gt;

&lt;p&gt;5.5 Skip Tool Chain Installation, we have already installed it. Go to Configuring the Development Environment. There we make all further configurations.&lt;/p&gt;

&lt;p&gt;Next steps (6-12) are taken in the ./cpss_release_git_CPSS_4.2_2020_03_018/cpss directory &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Build the kernel and the device tree
&lt;/h2&gt;

&lt;p&gt;6.1 &lt;code&gt;git checkout cpss_4.2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;6.2 &lt;code&gt;make ARCH=arm CROSS_COMPILE=$(pwd)/../../armv7-marvell-linux-gnueabihf-hard-5.2.1_x86_64_20160301/bin/arm-marvell-linux-gnueabihf- TARGET=armv7 FAMILY=DX DEBUG_INFO=Y kernel&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Assemble CPSS
&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;make ARCH=arm CROSS_COMPILE=$(pwd)/../../armv7-marvell-linux-gnueabihf-hard-5.2.1_x86_64_20160301/bin/arm-marvell-linux-gnueabihf- TARGET=armv7 FAMILY=DX DEBUG_INFO=Y appDemo&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Build the kernel modules to make CPSS work
&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;make ARCH=arm CROSS_COMPILE=$(pwd)/../../armv7-marvell-linux-gnueabihf-hard-5.2.1_x86_64_20160301/bin/arm-marvell-linux-gnueabihf- TARGET=armv7 FAMILY=DX DEBUG_INFO=Y modules&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Marvell provides 3 kernel modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mvIntDrv.ko — for processing interrupts from/for Packet Processor.&lt;/li&gt;
&lt;li&gt;mvDmaDrv.ko — o for allocating the DMA memory that sends packets to/from the CPU.&lt;/li&gt;
&lt;li&gt;mvMbusDrv.ko — for accessing internal resources when using Prestera's internal processor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, let’s assemble the file system: &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9: Download the busybox 1.21.1
&lt;/h2&gt;



&lt;p&gt;&lt;code&gt;mkdir busybox &amp;amp;&amp;amp; wget -P busybox https://busybox.net/downloads/busybox-1.21.1.tar.bz2&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10: Fix the Makefile
&lt;/h2&gt;

&lt;p&gt;Open the root Makefile in cpss_release_git_CPSS_4.2_2020_03_018/cpss&lt;/p&gt;

&lt;p&gt;and replace the line:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tools/build/rootfs/crfs.sh $(BUILD_FOLDER)/rootfs $(CROSS_COMPILE) /nfs/pt/swdev/areas/readonly/swtools/devsources/root_fs/files/busybox/busybox-1.22.1.tar.bz2; \&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tools/build/rootfs/crfs.sh $(BUILD_FOLDER)/rootfs $(CROSS_COMPILE) $(MY_DIR)/busybox/busybox-1.21.1.tar.bz2; \&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 11: Build the file system
&lt;/h2&gt;

&lt;p&gt;Instead of storing on the device, the file system will be stored on a RAM disk. The RAM disk will be loaded into the device RAM. This is the most beneficial storage option, since the amount of memory used does not exceed 256 MB.&lt;/p&gt;

&lt;p&gt;11.1 &lt;code&gt;make ARCH=arm CROSS_COMPILE=$(pwd)/../../armv7-marvell-linux-gnueabihf-hard-5.2.1_x86_64_20160301/bin/arm-marvell-linux-gnueabihf- TARGET=armv7 FAMILY=DX DEBUG_INFO=Y rootfs&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We have already built the CPSS and the module to work with it in steps 7 and 8. Now copy them into the file system:&lt;/p&gt;

&lt;p&gt;11.2 &lt;code&gt;cp compilation_root/cpss_4.2/armv7_DX/appDemo cpssEnabler/mainExtDrv/src/gtExtDrv/linuxNoKernelModule/drivers/mvDmaDrv.ko cpssEnabler/mainExtDrv/src/gtExtDrv/linuxNoKernelModule/drivers/mvIntDrv. ko cpssEnabler/mainExtDrv/src/gtExtDrv/linuxNoKernelModule/drivers/mvMbusDrv.ko compilation_root/cpss_4.2/armv7_DX/rootfs/home/user/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Compile a file system image that is suitable for u-boot. We do this with mke2fs and mkimage: &lt;/p&gt;

&lt;p&gt;11.3 &lt;code&gt;cd compilation_root/cpss_4.2/armv7_DX &amp;amp;&amp;amp; mke2fs -L '' -N 0 -O ^64bit -d rootfs -t ext2 rootfs.ext2 256M &amp;amp;&amp;amp; gzip rootfs.ext2 &amp;amp;&amp;amp; mkimage -A arm -O linux -T ramdisk -C gzip -n "Build Root File System" -d rootfs.ext2.gz rootfs.ext2.gz.uboot &amp;amp;&amp;amp; cd -&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The kernel, device tree, and RAM disk of the file system will be booted to the device via TFTP. It is also possible to write them to the NAND-memory of the device after the end of the development and debugging cycle. But we will stop with TFTP. You will need a connection between the host machine and the device (Ethernet port on the back of the device) and a TFTP server on the host.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 12: Install and configure the TFTP server
&lt;/h2&gt;

&lt;p&gt;12.1 &lt;code&gt;sudo apt install -y tftpd-hpa&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;12.2 &lt;code&gt;sudo systemctl enable tftpd-hpa &amp;amp;&amp;amp; sudo systemctl restart tftpd-hpa&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Copy the kernel, device tree, and RAM disk file system to /var/lib/tftpboot. /var/lib/tftpboot is the home directory for the TFTP server.&lt;/p&gt;

&lt;p&gt;12.3 &lt;code&gt;sudo cp ../kernel/arch/arm/boot/zImage ../kernel/arch/arm/boot/dts/armada-38x-interposer.dtb compilation_root/cpss_4.2/armv7_DX/rootfs.ext2.gz.uboot /var/lib/tftpboot&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 13: Set up u-boot on the device
&lt;/h2&gt;

&lt;p&gt;13.1 Plug the Ethernet cable into the MGMT port on the back of the unit – this is the TFTP connection.&lt;/p&gt;

&lt;p&gt;13.2 Connect the RS232 (host) – RJ-45 (device) cable to the CONSOLE port – this is your console.&lt;/p&gt;

&lt;p&gt;13.3 Start minicom to connect to the device console. Port settings: 115200 8N1.&lt;/p&gt;

&lt;p&gt;13.4 Turn on the device. Immediately, the bootloader gives the message: "Hit any key to stop autoboot:". Press any key to enter the u-boot settings menu.&lt;/p&gt;

&lt;p&gt;13.5 Perform the following commands one by one in the u-boot console:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;setenv bootcmd "run bootcmd_ram ;"&lt;/li&gt;
&lt;li&gt;setenv bootcmd_ram "run tftp_ramdisk; setenv bootargs $console root=/dev/ram0 rw; tftp $loadaddr $image_name; tftp $fdtaddr $fdtfile; bootz $loadaddr ${ramdisk_addr}:${initrd_size} $fdtaddr ;"&lt;/li&gt;
&lt;li&gt;setenv tftp_ramdisk "tftp $ramdisk_addr $ramdisk_name; &lt;/li&gt;
&lt;li&gt;setenv initrd_size ${filesize}"&lt;/li&gt;
&lt;li&gt;setenv ramdisk_addr "0x05200000".&lt;/li&gt;
&lt;li&gt;setenv ramdisk_name "rootfs.ext2.gz.uboot"&lt;/li&gt;
&lt;li&gt;setenv console "ttyS0,115200"&lt;/li&gt;
&lt;li&gt;setenv loadaddr "0x02000000"&lt;/li&gt;
&lt;li&gt;setenv image_name "zImage"&lt;/li&gt;
&lt;li&gt;setenv fdtaddr "0x1000000"&lt;/li&gt;
&lt;li&gt;setenv fdtfile "armada-38x-interposer.dtb"&lt;/li&gt;
&lt;li&gt;saveenv&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;13.6 Boot! :-)&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 14: Ensure, that the CPSS application works on the device
&lt;/h2&gt;

&lt;p&gt;Load the kernel modules:&lt;/p&gt;

&lt;p&gt;14.1 &lt;code&gt;cd /home/user &amp;amp;&amp;amp; insmod mvDmaDrv.ko &amp;amp;&amp;amp; insmod mvIntDrv.ko &amp;amp;&amp;amp; insmod mvMbusDrv.ko&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run the CPSS application:&lt;/p&gt;

&lt;p&gt;14.2 ./appDemo&lt;/p&gt;

&lt;p&gt;This takes you to the console of the CPSS application. In the console we can configure the Ethernet ports on the switch and the entire Prestera system. To check the application workability, we will connect one of the switch front panel Ethernet ports (any port) to a free port on the host machine. After linking them together, ping the host machine with the following commands:&lt;/p&gt;

&lt;p&gt;14.3: autoInitSystem — initialize the Prestera system – this command must be executed after each reboot of the switch.&lt;/p&gt;

&lt;p&gt;14.4: Next, run the following commands one by one&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;configure&lt;/li&gt;
&lt;li&gt;mac address 00:00:00:00:11:22&lt;/li&gt;
&lt;li&gt;interface ethernet 0/35&lt;/li&gt;
&lt;li&gt;ip address  &lt;/li&gt;
&lt;li&gt;force link up&lt;/li&gt;
&lt;li&gt;end&lt;/li&gt;
&lt;li&gt;traffic&lt;/li&gt;
&lt;li&gt;protocol enable arp&lt;/li&gt;
&lt;li&gt;protocol enable ping&lt;/li&gt;
&lt;li&gt;ping &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the ping is successful, you will see the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Console(traffic)# ping 192.168.15.3&amp;gt;

&amp;lt;Pinging 192.168.15.3 using src mac: 00:00:00:00:11:22 src ip:192.168.15.10&amp;gt;

&amp;lt;Ping to ip 192.168.15.3 successful.&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Congratulations!&lt;/strong&gt; You've just configured Linux and CPSS on the Marvell RD-AC3X-48G4X2XL-A board with the Prestera DX Ethernet switch! &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6o4be8inm9uwez1kggy.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6o4be8inm9uwez1kggy.jpeg" alt="Industrial Ethernet switch designed by Promwad" width="800" height="331"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Picture: Industrial Ethernet switch 1Gb/10Gbps based on OS Linux, developed on the same family of network chips as the debugger (48 downlink ports + 4 uplink ports, operating range: -20–70°C)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This guide is helpful for both theory and practice. You can explore the capabilities of the Marvell Prestera switch (L2, CAPWAP, CNC, DCE, PHY, EEE, IP, NAT, etc.) together with the Lua CLI or develop your own high-level Marvell Prestera-based application for &lt;a href="https://promwad.com/solutions/telecom?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=cpss" rel="noopener noreferrer"&gt;network equipment&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A full description of the CPSS commands you can find in the User guide from Step 3 in the Lua CLI User Guide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; Please, feel free to follow me here or on &lt;a href="https://www.linkedin.com/in/vanokuten/" rel="noopener noreferrer"&gt;my LinkedIn profile&lt;/a&gt; where I share engineering and business articles on the electronics design and manufacturing.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>linux</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Develop &amp; Publish Tizen Apps for Samsung Smart TV: Our Guide for Javascript Engineers</title>
      <dc:creator>Ivan Kuten</dc:creator>
      <pubDate>Thu, 08 Jul 2021 08:42:47 +0000</pubDate>
      <link>https://forem.com/ivan_kuten/how-to-develop-publish-tizen-apps-for-samsung-smart-tv-our-guide-for-javascript-engineers-3mk9</link>
      <guid>https://forem.com/ivan_kuten/how-to-develop-publish-tizen-apps-for-samsung-smart-tv-our-guide-for-javascript-engineers-3mk9</guid>
      <description>&lt;p&gt;&lt;em&gt;This article is about the amazing adventures of JS developers in the world of Tizen OS. It will include a step-by-step setup of the integrated environment (IDE), &lt;a href="https://promwad.com/solutions/video-streaming/smart-tv?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=tizen" rel="noopener noreferrer"&gt;development of Smart TV&lt;/a&gt; apps, their submission to the Tizen Store — and, of course, code samples and case studies.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you share our belief that Javascript is the best programming language working almost everywhere, from your grandma’s Smart TVs to the SpaceX ships, welcome to our guide.&lt;br&gt;
So, you’re a front-end developer having a big, beautiful, 65-inch Samsung Tizen TV. And you have it for a reason because you need to design a TV application based on Javascript: with an &lt;a href="https://promwad.com/solutions/video-streaming/hls-player?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=tizen" rel="noopener noreferrer"&gt;HLS player&lt;/a&gt; or DASH streams from some vendors, a bit of DRM, and other not yet clear acronyms. Nothing complicated, nothing personal.&lt;/p&gt;

&lt;p&gt;There’s no room for retreat; you have to deal with it. Let’s get to the bottom of this together with the Promwad engineering team.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing Software and Setting up the Environment
&lt;/h2&gt;

&lt;p&gt;The first thing to do is to go to the official website to get &lt;a href="https://developer.tizen.org/development/tizen-studio/download" rel="noopener noreferrer"&gt;Tizen Studio&lt;/a&gt;. We are downloading this toolkit with particular attention to the &lt;a href="https://docs.tizen.org/application/tizen-studio/setup/prerequisites/" rel="noopener noreferrer"&gt;Prerequisites&lt;/a&gt; section with system requirements and needed components.&lt;/p&gt;

&lt;p&gt;Tizen Studio is an integrated development environment or IDE for Tizen that enables you to create real and virtual devices, connect platforms, create certificates and run applications.&lt;/p&gt;

&lt;p&gt;Optionally, you can install &lt;a href="https://docs.tizen.org/application/vscode-ext/web/" rel="noopener noreferrer"&gt;the VSCode Extension for Tizen&lt;/a&gt;, it helps manage our IDE without leaving the editor.&lt;/p&gt;
&lt;h2&gt;
  
  
  Instructions for Mac on the Apple Silicon Platform
&lt;/h2&gt;

&lt;p&gt;If you have a new ARM64-based Mac, you can install tizen-studio by doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;right click on installer.app in Finder&lt;/li&gt;
&lt;li&gt;select Show Package Contents&lt;/li&gt;
&lt;li&gt;go to Contents/Resources/Java&lt;/li&gt;
&lt;li&gt;unzip tizen-sdk.zip&lt;/li&gt;
&lt;li&gt;copy the tizen-sdk/jdk folder to ~/.package-manager/&lt;/li&gt;
&lt;li&gt;run installer.app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When the stars are aligned, once the installation is complete, you need to open Package Manager and add the following extensions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Samsung Certificate Extension;&lt;/li&gt;
&lt;li&gt;TV Extension Tools;&lt;/li&gt;
&lt;li&gt;and the current platform (now it is TV-Extension-6.0).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Judging by the download speed, these packets are coming directly from the Korean servers. :-) While waiting for the installation to complete, you can read about the differences between &lt;a href="https://en.wikipedia.org/wiki/HTTP_Live_Streaming" rel="noopener noreferrer"&gt;HLS&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP" rel="noopener noreferrer"&gt;DASH&lt;/a&gt; and between &lt;a href="https://en.wikipedia.org/wiki/PlayReady" rel="noopener noreferrer"&gt;PlayReady&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Widevine" rel="noopener noreferrer"&gt;Widevine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(…6 hours later)&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Switching Your TV to Developer Mode
&lt;/h2&gt;

&lt;p&gt;It’s time to move your TV to Developer Mode and add it to Tizen Studio.&lt;/p&gt;

&lt;p&gt;To do this, go to Apps and press the magic sequence 1, 2, 3, 4, 5 on your remote control. As a result, the developer mode window opens.&lt;/p&gt;

&lt;p&gt;If you have a full-featured remote with a numpad, you’re in luck. With a mini remote controller, it’s going to be a bit more tricky: you should open the on-screen numeric keypad (numpad) and press 1–2–3 buttons using the direction buttons (d-pad).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs27iz89wchhk34z5etz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs27iz89wchhk34z5etz.png" alt="2_samsung_smart_tv_tizen_app_development" width="785" height="407"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;At the top: a full-featured remote control with a numpad and d-pad for advanced users and developers. At the bottom: a mini remote control for Smart TV with control buttons in the center.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the pop-upped Developer Mode window, type in the IP of your device with Tizen Studio, reboot your Smart TV, and voila — you can open Device Manager and add your big and beautiful 65" TV.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding Your TV to IDE via Device Manager
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93l9x6mrx3069iwps2j7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F93l9x6mrx3069iwps2j7.png" alt="3_samsung_smart_tv_tizen_app_development" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Screenshot: Device Manager with a connected TV.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Several conditions must be met for a TV to be successfully added to Device Manager:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the TV is switched to Developer Mode;&lt;/li&gt;
&lt;li&gt;the Developer Mode window shows the correct IP of your working machine with Tizen Studio installed;&lt;/li&gt;
&lt;li&gt;devices are on a shared network: LAN, WiFi, or VPN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;[Optional] After adding a TV in Tizen Studio, you can copy its unique DUID, so it would be easier to create a certificate later. And if there are a lot of TVs (just in case), it is better to put all DUIDs into a text file in — one DUID per line.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tizen Simulator and Emulator
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.tizen.org/development/tizen-studio/web-tools/running-and-testing-your-app/emulator?langredirect=1" rel="noopener noreferrer"&gt;The Tizen Emulator&lt;/a&gt; is almost a full-fledged replacement for a real device. It supports the emulation of processor, memory, peripherals, events, codecs, and graphics. However, there is no support for DRM or tech tools for digital rights management.&lt;/p&gt;

&lt;p&gt;We advise you to download the 4.1.2 platform to run the emulator on it — it runs faster and takes up less memory space than others. You can find it in the archive section of &lt;a href="https://developer.samsung.com/smarttv/develop/tools/tv-extension/archive.html" rel="noopener noreferrer"&gt;the TV Extension for Tizen SDK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A complete list of differences between the emulator and the real device can be found &lt;a href="https://developer.tizen.org/ko/development/tizen-studio/web-tools/running-and-testing-your-app/emulator?langredirect=1#target" rel="noopener noreferrer"&gt;in the corresponding&lt;/a&gt; section on developer.tizen.org&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.tizen.org/development/tizen-studio/web-tools/using-web-simulator?langredirect=1" rel="noopener noreferrer"&gt;Web Simulator&lt;/a&gt; is a lightweight version of the emulator in Chrome. There is virtually no API, and the rest is simulated with JS returning stub values. You can use it to test various screen resolutions and some basic stuff, but there are more limitations than opportunities.&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding a Certificate on Your TV
&lt;/h2&gt;

&lt;p&gt;Now it’s time to create certificates with the Certificate Manager. They will allow installing your application on your TV or emulator and publishing it on the Tizen Store. There are two types of certificates: Tizen and Samsung.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukvcws5dfee7hjr777v5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukvcws5dfee7hjr777v5.png" alt="4_samsung_smart_tv_tizen_app_development" width="800" height="415"&gt;&lt;/a&gt;&lt;em&gt;Screenshot: Samsung Certificate Manager.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Choose the Samsung certificate, it will allow you to install applications on your TV. To do this, you will need to create an account in &lt;a href="https://seller.samsungapps.com/tv/portal/main" rel="noopener noreferrer"&gt;Seller Office&lt;/a&gt;, a special section for Tizen developers on the Samsung website.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtkude2a0nlkzmwfwbti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtkude2a0nlkzmwfwbti.png" alt="5_samsung_smart_tv_tizen_app_development" width="506" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;New accounts are confirmed manually, so you have to wait a bit — this is the main inconvenience of creating the first certificate. You will get &lt;strong&gt;the Public level&lt;/strong&gt; by default, which is enough for most tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Partner level&lt;/strong&gt; opens up more opportunities. To get it, you have to pass a quest in the Seller Office and wait for confirmation from two weeks to two months. (That was the case even before the COVID-19 pandemic!).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Platform level&lt;/strong&gt; is inaccessible to mere mortals.&lt;/p&gt;

&lt;p&gt;The Tizen certificate is needed to test the application in the emulator ONLY. Its main advantage is your freedom. Freedom of choice: Public and Partner levels with its advanced API are available out of the box.&lt;/p&gt;

&lt;p&gt;As a result, you will have a profile with two certificates — author and distributor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Take kare of your certificate (author.p12) and password, make a backup immediately, save it in a safe place, and send it to your client. Without it, you won’t be able to update the app in the Tizen Store.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Our tip for Tizen developers&lt;/strong&gt;: before creating a certificate, enable your TV in Device Manager, then its DUID will be added to the distributor certificate automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tyikfyrnzf2ob1v3oiq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5tyikfyrnzf2ob1v3oiq.png" alt="6_samsung_smart_tv_tizen_app_development" width="800" height="272"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The Promwad’s profile with two certificates for Tizen OS: author and distributor.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To summarize. A certificate is needed for the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wgt file signature to install on your device or emulator;&lt;/li&gt;
&lt;li&gt;publishing your app on the Tizen Store;&lt;/li&gt;
&lt;li&gt;certificate level defines a set of functions available from the device API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read more about certificates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.tizen.org/application/web/tutorials/sign-certificate/" rel="noopener noreferrer"&gt;https://docs.tizen.org/application/web/tutorials/sign-certificate/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.tizen.org/application/dotnet/tutorials/certificates/creating-certificates/" rel="noopener noreferrer"&gt;https://docs.tizen.org/application/dotnet/tutorials/certificates/creating-certificates/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last step is to install the certificate on the TV. Without this, you will not be able to install your application on it. You need the Samsung certificate. Done!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8ciclmfvtbfglf3chvv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff8ciclmfvtbfglf3chvv.png" alt="7_samsung_smart_tv_tizen_app_development" width="800" height="583"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Screenshot: Installing the certificate on your Smart TV.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Developing Web Apps on Tizen: Varieties and (Un)Usability
&lt;/h2&gt;

&lt;p&gt;Tizen has two types of web applications: packaged and hosted.&lt;/p&gt;

&lt;p&gt;A typical packaged application is installed on your TV and stores all resources locally — styles, scripts, templates, images, config.xml, etc. When developing or debugging such an application, you have to wait for the wgt file to be built, downloaded, and installed on the device. Writing styles, developing new modules, or debugging player behavior promises pain, frustration, and a great deal of time is lost in reconstructing the context.&lt;/p&gt;

&lt;p&gt;The best solution in the early stages would be to develop an app for the Chrome desktop version. When preparing HTML layouts and debugging navigation, you can also do without a TV.&lt;/p&gt;

&lt;p&gt;Lucky owners of the Samsung Partner level certificate can choose a hosted application. The TV acts as a resource loader, and the development process goes as the usual browser-based one. To work with hosted applications, you will need to do two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add to the project your favorite http server with autoreload.&lt;/li&gt;
&lt;li&gt;Create an empty project in Tizen Studio and add a redirect to the local machine IP to index.html.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;MyApp&amp;lt;/title&amp;gt;
&amp;lt;meta http-equiv=“refresh” content=”0;url=http://YOUR_IP"&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Done! The TV now acts as a webview.&lt;/p&gt;

&lt;p&gt;The main disadvantage of such a solution is the reduced API of the webapis device. This thing is critical if you need, for example, to get DUID of your device to bind it with the back-end.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;webapis.productinfo.getDuid()
Cannot read property 'getDuid' of undefined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Meanwhile, the Tizen API remains fully available: you can add RCU buttons, control volume, etc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tizen.tvinputdevice.registerKey("ChannelUp");
success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What Code Is Used to Develop Apps for the Samsung Smart TVs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Javascript (ES5 and ES6)&lt;/strong&gt;&lt;br&gt;
In 2017, Tizen started partial support of the third coming of Javascript (ES6). Full support was implemented for the 2018 models. It is better to read the specification in person; and there may be surprises:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.samsung.com/smarttv/develop/specifications/web-engine-specifications.html#javascript-es6" rel="noopener noreferrer"&gt;https://developer.samsung.com/smarttv/develop/specifications/web-engine-specifications.html#javascript-es6&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For old-timers, you have to use &lt;a href="http://vanilla-js.com/" rel="noopener noreferrer"&gt;vanilla.js&lt;/a&gt; or transpilate the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. React&lt;/strong&gt;&lt;br&gt;
The answer is yes. We haven’t tried it, but a similar version is described on Stackoverflow: &lt;a href="https://stackoverflow.com/questions/57773000/how-do-i-build-a-create-react-app-in-tizen" rel="noopener noreferrer"&gt;It’s a little challenging, but you can do it&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. React Native&lt;/strong&gt;&lt;br&gt;
If you are a React Native developer, try &lt;a href="https://renative.org/docs/platform-tizen" rel="noopener noreferrer"&gt;ReNative&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Chromium and Webkit to run web apps on Tizen
&lt;/h2&gt;

&lt;p&gt;Tizen has the Chromium engine to run web applications. This is true for 2017–2021+ TV models. The 2015 and 2016 models run apps on the Webkit engine and, despite obsolescence, there are still plenty of them in users’ homes. Gradually, Samsung is removing them from its app store. For example, today, you can no longer release a product for 2015 TVs.&lt;/p&gt;

&lt;p&gt;The version of the engine does not shine like a new one and can not be updated. The 2021 model has Chromium M76 version released two years ago.&lt;/p&gt;

&lt;p&gt;The reality is the following: to support current devices, you have to deal with the Chromium M47 version from back in 2015. What did you do in 2015? Ugh…&lt;/p&gt;

&lt;p&gt;If that’s not enough, welcome to the support of 2016 TVs with the Webkit version of the mysterious r152340 revision. But let’s not talk about sad things.&lt;/p&gt;
&lt;h2&gt;
  
  
  Debugging Web Apps on Tizen
&lt;/h2&gt;

&lt;p&gt;For debugging, you can use Chrome DevTools no older than version 79. That’s because on a chilly February morning in 2020, Google removed support for Custom Elements V0 starting with the 80 version, and those developer tools had since become incompatible with Tizen.&lt;/p&gt;

&lt;p&gt;Workarounds like “Go to Preferences &amp;gt; Tizen Studio &amp;gt; Web &amp;gt; Chrome &amp;gt; Extra parameters” and add — enable-blink-features=CustomElementsV0 — user-data-dir=/tmp/tmpchromeuser do not work.&lt;/p&gt;

&lt;p&gt;Our choice is to install the 79th version &lt;a href="https://www.slimjet.com/chrome/google-chrome-old-version.php" rel="noopener noreferrer"&gt;from the archive www.slimjet.com/chrome&lt;/a&gt; and disable auto-update.&lt;/p&gt;

&lt;p&gt;For a TV from 2016 on Webkit, the DevTools from Chrome v62 or so will do. There is a high probability of getting a frozen screen on your TV if you press the “wrong” button in DevTools.&lt;/p&gt;
&lt;h2&gt;
  
  
  Publishing Your App: Seller Office and Tizen Store
&lt;/h2&gt;

&lt;p&gt;It’s time to submit and publish your app for the Tizen Store. To do this, you need to prepare or request several things from your client:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Application logos&lt;/strong&gt; according to the UX manuals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A full-screen pic with two layers: the logo itself (transparent PNG) and the background. Size: 1920x1080px, 300 kilobytes max.&lt;/li&gt;
&lt;li&gt;An icon for search results (512x423px), 300 kilobytes max.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94w0f3bsmebvrmibi4au.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F94w0f3bsmebvrmibi4au.png" alt="8_samsung_smart_tv_tizen_app_development" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Full-size screenshots&lt;/strong&gt; of the main application screens — 4 pics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru4kbdz6l6xj6p9wo1nf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fru4kbdz6l6xj6p9wo1nf.png" alt="9_samsung_smart_tv_tizen_app_development" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A DOC file in English&lt;/strong&gt; with a description of your screens and behavior of your application according to the following checklist:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;UI structure displaying navigation between your app screens.&lt;/li&gt;
&lt;li&gt;Use cases showing how to use the main features of your app.&lt;/li&gt;
&lt;li&gt;Menus and functions — labeling and description of the main functions.&lt;/li&gt;
&lt;li&gt;Remote control keys and their functions.&lt;/li&gt;
&lt;li&gt;Language options.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything seems to be strict and clear in this &lt;a href="https://developer.samsung.com/smarttv/develop/distribute/launch-checklist/application-ui-description.html" rel="noopener noreferrer"&gt;official developer’s checklist&lt;/a&gt;, but as our practice shows, a simple document with UI screenshots and a description of your main functions and buttons is OK.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Specify the version&lt;/strong&gt; of your application in config.xml and prepare a signed wgt file.&lt;/p&gt;

&lt;p&gt;We’re good to go! The rest of the quest requires no prior preparation. You can go directly to the registration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa12m2dc5nl5xsc53o2ib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa12m2dc5nl5xsc53o2ib.png" alt="10_samsung_smart_tv_tizen_app_development" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After successfully completing the registration, the manual testing process by Samsung begins. Their people add bugs to the internal bug tracker, attach silent videos there, and point out moments of your fiasco.&lt;/p&gt;

&lt;p&gt;As a result, the application will appear in the Samsung Store, even if it has minor defects, such as “Many of channels don’t work. Black screen with loader is visible”. :-)&lt;/p&gt;

&lt;p&gt;But with critical defects like “Infinite loading,” the application will not make it to users.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggv1wndk1re3florewhf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fggv1wndk1re3florewhf.png" alt="11_samsung_smart_tv_tizen_app_development" width="800" height="337"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Screenshot: the bug tracking system on Samsung’s portal for Tizen developers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After fixing the critical bugs, you can celebrate your success! The app can now be found by name or keywords in the Smart TV search.&lt;/p&gt;
&lt;h2&gt;
  
  
  Documentation for Tizen Apps Developers
&lt;/h2&gt;

&lt;p&gt;The documentation is there, thank you very much.&lt;/p&gt;

&lt;p&gt;It was written by different people at different times, so terminology and style changes from document to document, and in the guides have unworkable code. You can find a striking illustration in the example of using an embedded player: webapi instead of webapis. And the main thing: &lt;a href="https://developer.samsung.com/smarttv/develop/guides/multimedia/media-playback/using-avplay.html" rel="noopener noreferrer"&gt;this unfortunate typo&lt;/a&gt; was in the DRM settings section! We are sure that we were not the only ones who reported this problem to the Sellers Office, but three years later the problem is still there.&lt;/p&gt;
&lt;h2&gt;
  
  
  Helpful Notes for Tizen developers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Registration and Support for Remote Control Buttons&lt;/strong&gt;&lt;br&gt;
The first thing you have to deal with when developing Tizen-based apps is registering the remote control buttons. &lt;/p&gt;

&lt;p&gt;Some buttons will not be available in the app by default, and you need to register them first.&lt;/p&gt;

&lt;p&gt;Individually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tizen.tvinputdevice.registerKey('MediaPlayPause');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or as a bunch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const keys = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 
"ChannelUp", "ChannelDown", "MediaPlay", "MediaPause",
"MediaFastForward", "MediaRewind", "Exit"];

tizen.tvinputdevice.registerKeyBatch(keys, successCb, errorCb);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is better not to register VolumeUp, VolumeDown and VolumeMute buttons, otherwise, their native functionality will require program processing via API.&lt;/p&gt;

&lt;p&gt;The rest is easy. Catching clicks in the application with the Listener:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;document.body.addEventListener('keydown', handleKeyDown);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where handleKeyDown will pass the button code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Useful Tizen and Webapis Calls&lt;/strong&gt;&lt;br&gt;
A list of useful calls for the Tizen developers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;tizen.systeminfo.getCapability("http://tizen.org/feature/network.ethernet");
tizen.systeminfo.getCapability("http://tizen.org/system/model_name");
tizen.systeminfo.getPropertyValue("ETHERNET_NETWORK”, successCb, errorCb);
webapis.productinfo.getFirmware()
"T-KTM2DEUC-1202.3"
webapis.productinfo.getModel()
UNU7400"
webapis.productinfo.getVersion()
"3.0"
webapis.productinfo.getRealModel()
"UE43NU7400"
webapis.productinfo.getModelCode()
"18_KANTME_UHD"
webapis.productinfo.getLocalSet()
"EU_LITHUANIA"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Curious Cases We Encountered in Our Clients’ Projects at Promwad
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Case Study #1: Voice Control Support (Korea vs. Others)&lt;/strong&gt;&lt;br&gt;
Voice control is completely helpless and ruthless at the same time. What it should look like: you say to your remote “TV, I want coffee” and 10 minutes later a courier delivers you a cappuccino. The manufacturer writes nicely about “you can register general voice commands, which trigger a listener when the user speaks them,” but behind every “can” is a “must”. As is usually the case, two troubles merged into one: the need to pre-register commands and poor voice recognition. And if you or your client gets the idea of adding voice control, be prepared to supplement the Volume Up and Louder dictionaries not only with synonyms but also with the similar-sounding Bloom Up and Laura.&lt;/p&gt;

&lt;p&gt;Everything is much better in the Korean TV interface. But, as their folk proverb says, “How can you wag a tail if you don’t have one?”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case Study #2: Quick Transition Inside the App and Deep Link&lt;/strong&gt;&lt;br&gt;
The prize in the “least used feature” category goes to Smart Hub Preview, which gives you direct access to the internal sections of the app. With this kind of linking, you can feature content or send your users directly to some favorite section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsd54do7ooqhx9x8c9b7x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsd54do7ooqhx9x8c9b7x.png" alt="12_samsung_smart_tv_tizen_app_development" width="749" height="326"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The scheme shows an example of featured content.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Case Study #3: Mpd Stream Bug With 50 Days&lt;/strong&gt;&lt;br&gt;
When porting one project to Tizen 4.0 for the 2017 model, we had a problem: the sound did not work when playing live broadcasts (MPD streaming). The Volume Up/Down/Mute buttons and the sound control through API did not help. On other platforms — for example, LG Smart TV (WebOS) — there was no problem. The link to the MPD stream and the file content also did not cause problems — all tags and directives were supported by Tizen.&lt;/p&gt;

&lt;p&gt;We had sound in &lt;a href="https://github.com/Dash-Industry-Forum/dash-live-source-simulator/wiki/Test-URLs" rel="noopener noreferrer"&gt;our test streams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our doubts were related only to the availabilityStartTime directive, which specifies a zero point on the timeline and is defaulted to Unix epoch, i.e. 1970–01–01T00:00:00Z.&lt;/p&gt;

&lt;p&gt;It turned out that in streams with the value of availabilityStartTime greater than 49.7 days, the sound was absent or disappeared within the playback process. And it made sense because 49.7 days or 2,147,483,647 milliseconds or 2**32 equals the maximum positive integer value in 32-bit systems (Number.MAX_SAFE_INTEGER). Simply put, there was just a bug in the Tizen multimedia stack, and there was nothing we could do about it.&lt;/p&gt;

&lt;p&gt;How was it solved? The next day the TV automatically updated the firmware to version 1251, and the problem disappeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Tizen holds a solid market share, the platform is developing, new versions of TVs and software are coming out. At the same time, development does not become easier or more comfortable and is full of frustration. The attempt to create a single platform for all devices at once is ambiguous.&lt;/p&gt;

&lt;p&gt;The biggest problem is documentation and usability. It covers all versions of all devices at once — web and native apps — and is full of bugs and flaws.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.tizen.org/development" rel="noopener noreferrer"&gt;The developer.tizen.org website&lt;/a&gt; loads slowly enough to feel this (3–8 seconds), and it hasn’t changed in recent years. The search is so awkward that it is more convenient to google something and go to the main site, but it is important to make sure that the article or guide refers exactly to your TV and to the web version of the application. And the automatic switching of the site to its Korean version is a common thing.&lt;/p&gt;

&lt;p&gt;The forums for Tizen app developers are filled with typical problems. Answers with outdated links lead to “pagenotfound” 99% of the time, and communication with the Seller Office is useless 100% of the time. You will most likely wait three weeks to get an answer that is irrelevant to the question. And that’s for 30% of your profits if you release a paid application.&lt;/p&gt;

&lt;p&gt;Testing feels a lot like the lottery. To build a working player for &lt;a href="https://promwad.com/solutions/video-streaming?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=tizen" rel="noopener noreferrer"&gt;video streaming&lt;/a&gt;, let alone DRM or advertising support is a challenging task for advanced engineers. :-) It’s not for nothing that Tizen promotes the paid 3rd party NexPlayer as “the only video player recommended by Samsung” — you should use it.&lt;/p&gt;

&lt;p&gt;We suspect that some paragraphs of our guide may have caused your frustration and discourage you from Tizen. Nevertheless, if things were simple, this article would not have been born, so we’ll wrap it up on a positive note: Tizen is globally ranked first among all operating systems for Smart TV. Last year, this OS covered &lt;a href="https://www.digitaltvnews.net/?p=36107" rel="noopener noreferrer"&gt;13% of the global market&lt;/a&gt; and &lt;a href="https://www.digitaltvnews.net/?p=36143" rel="noopener noreferrer"&gt;30% in the UK&lt;/a&gt;. Judging by the recent forecasts, Samsung is not going to lose its position.&lt;/p&gt;

&lt;p&gt;Even in the U.S. and Canada, where the leader board of Smart TV OS differs from all other regions (they &lt;a href="https://www.theverge.com/2021/1/8/22220330/roku-tv-number-one-smart-os-us-canada-2020" rel="noopener noreferrer"&gt;prefer Roku&lt;/a&gt; there), Tizen is still in the top three along with Amazon Fire TV. So if you or your customers are planning to release apps for a wide international audience, Tizen is your must-have, despite all the pain and tears for front-end developers who write JS code for this operating system. At least we at Promwad Electronics Design House can confirm from our experience that with each newly published &lt;a href="https://promwad.com/case-studies/sport-club-application-smart-tv?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=tizen" rel="noopener noreferrer"&gt;application for Tizen Store&lt;/a&gt;, your next one will be easier and faster to release&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Korean proverb says “No gains without pains” (노력 없이는 이득도 없다). Thanks for reading!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;em&gt;About the Promwad Blog&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Hi, my name is Ivan Kuten. I’m a co-owner &amp;amp; CTO at &lt;a href="https://promwad.com/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=tizen" rel="noopener noreferrer"&gt;Promwad&lt;/a&gt;, where we design and manufacture for our clients new electronics and embedded software for smart TV, telecom, automotive, and other industries. Feel free to add me on &lt;a href="https://www.linkedin.com/in/vanokuten/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;; I’d love to connect with you and share my experience.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to develop Gstreamer-based video conferencing apps for RDK &amp; Linux set-top boxes</title>
      <dc:creator>Ivan Kuten</dc:creator>
      <pubDate>Fri, 23 Oct 2020 13:02:29 +0000</pubDate>
      <link>https://forem.com/promwad/how-to-develop-gstreamer-based-video-conferencing-apps-for-rdk-linux-set-top-boxes-1ak2</link>
      <guid>https://forem.com/promwad/how-to-develop-gstreamer-based-video-conferencing-apps-for-rdk-linux-set-top-boxes-1ak2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is our guest post for &lt;a href="https://www.cnx-software.com/" rel="noopener noreferrer"&gt;CNX Software&lt;/a&gt; that explains the basic steps to develop a video conferencing app with Gstreamer on TV boxes running Linux.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The COVID-19 pandemic has become a catalyst for new online services. For example, Zoom became so successful that it overtook IBM in terms of capitalization this month. The software engineers at Promwad were inspired by this success and decided to go even further: what about implementing &lt;a href="https://promwad.com/solutions/tv-conferencing" rel="noopener noreferrer"&gt;video conferencing on Smart TV and STBs&lt;/a&gt;? Then the users of such an application will have an opportunity to communicate not only at work but also to enjoy remote meetings with friends, cheer for a soccer team, watch a movie together, or do sports with a coach.&lt;/p&gt;

&lt;p&gt;For some reason, most digital TV operators do not have such a service, although, from an engineering point of view, all these features can be implemented on set-top boxes based on Linux/Android and &lt;a href="https://rdkcentral.com/" rel="noopener noreferrer"&gt;RDK&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s analyze the architecture of a Zoom-like video conferencing app for Smart TV and implement video stream encoding with &lt;a href="https://gstreamer.freedesktop.org/" rel="noopener noreferrer"&gt;GStreamer&lt;/a&gt; open-source multimedia framework. We collected information to work with this framework in pieces, but it was worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges and software architecture
&lt;/h2&gt;

&lt;p&gt;When developing the application architecture for set-top boxes, it is essential to consider all potential software and hardware limitations. Engineers who build desktop programs, as a rule, do not face these challenges, while it is a common thing for embedded engineers.&lt;/p&gt;

&lt;p&gt;So, what we are going to encounter on set-top boxes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Limited resources of CPU and devices themselves.&lt;/strong&gt; In most cases, STB devices use a variety of ARM processors, which implies several limitations and additional tasks, such as the need to use hardware encoding/decoding for a video stream. So, performance is a bottleneck.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different architectures in STBs by various manufacturers.&lt;/strong&gt; Some are based on Android; others use RDK or Linux-based distributions with their limitations and nuances. Therefore, it is better to choose the most common and cross-platform solutions in different software modules at the start of the development process. Not to mention the support of a desktop-version. And then move on to some particular cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network limits.&lt;/strong&gt; Many set-top boxes work both over Ethernet and Wi-Fi. Compression and transmission of video/audio streams is another bottleneck in applications of this kind.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety of stream transmission&lt;/strong&gt; and other data security issues.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support for cameras and microphones&lt;/strong&gt; on embedded platforms.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now we can cluster the architecture itself. Our video conferencing app for set-top boxes will consist of several large components and modules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Video stream capture&lt;/li&gt;
&lt;li&gt;Audio stream capture&lt;/li&gt;
&lt;li&gt;Network module&lt;/li&gt;
&lt;li&gt;Video/Audio Stream Encoding Module&lt;/li&gt;
&lt;li&gt;Video/Audio Stream Decoding Module&lt;/li&gt;
&lt;li&gt;Displaying a video conference on a screen&lt;/li&gt;
&lt;li&gt;Sound output&lt;/li&gt;
&lt;li&gt;Color transformations&lt;/li&gt;
&lt;li&gt;Several other secondary components&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a simplified form, the architecture can be depicted as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flajzrkiz8gl8nmak4b5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flajzrkiz8gl8nmak4b5e.png" alt="Architecture of video conferencing application for Smart TV" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we will focus on video stream decoding/encoding and possible implementation with the GStreamer framework, as it is one of the critical points in video conferencing app development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audio/video stream encoding and decoding
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Benefits of GStreamer for video conferencing
&lt;/h3&gt;

&lt;p&gt;As we have already noted, video streaming is one of our bottlenecks. Suppose you have a camera that outputs footage at 30 frames per second at a small resolution of 640×480. In total, it turns out in RGB24: 640 * 480 * 3 * 30 = 27,648,000 bytes per second, i.e., more than 26 megabytes per second, which won’t work for obvious reasons, notably network transmission bandwidth.&lt;/p&gt;

&lt;p&gt;One of the solutions is to implement video encoding using some library. As you can guess from the title of this article, our choice fell on the GStreamer framework. Why this particular library? Here are some of its advantages against other solutions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Good cross-platform solution with excellent support for Linux and Android.&lt;/li&gt;
&lt;li&gt;On RDK, Gstreamer is an encoding/decoding standard included in the default distribution.&lt;/li&gt;
&lt;li&gt;It supports a wide range of modules, filters, and codecs. For example, FFmpeg that can be used for the same purposes is one of GStreamer’s modules.&lt;/li&gt;
&lt;li&gt;Easy to build a pipeline. It’s easy to create a chain of encoding/decoding, and the pipeline approach enables smooth replacement of codecs, filters, etc. without the need to rewrite the code.&lt;/li&gt;
&lt;li&gt;C/C++ API is included.&lt;/li&gt;
&lt;li&gt;Support of hardware encoders/decoders, in particular, the &lt;a href="https://www.cnx-software.com/2011/11/11/openmax-open-media-acceleration/" rel="noopener noreferrer"&gt;OpenMAX API&lt;/a&gt; – a significant thing to work with set-top boxes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Exploring GStreamer and pipelines
&lt;/h3&gt;

&lt;p&gt;Before proceeding to code review, let’s look at what we can do without it.  GStreamer includes useful utilities to work with, in particular:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gst-inspect-1.0 will allow you to see a list of available codecs and modules, so you can immediately see what will do with it and select a set of filters and codecs.&lt;/li&gt;
&lt;li&gt;gst-launch-1.0 allows you to start any pipeline.
GStreamer uses a decoding scheme where a stream passes through different components in series, from source to sink output. You can choose anything as a source: a file, a device, the output (sink) also may be a file, a screen, network outputs, and protocols (like RTP).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A classic example of playing an mp4 file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gst-launch-1.0 filesrc location=file.mp4 ! qtdemux ! h264parse ! avdec_h264 ! videoconvert ! autovideosink&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The input accepts the mp4 file, which goes through the mp4 demuxer — qtdemux, then through the h264 parser, then through the decoder, the converter, and finally, the output.&lt;/p&gt;

&lt;p&gt;You can replace autovideosink with filesink with a file parameter and output the decoded stream directly to the file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Programming an application with GStreamer C/C++ API. Let’s try to decode
&lt;/h3&gt;

&lt;p&gt;Now when we know how to use gst-launch-1.0, we are doing the same thing within our application. The principle remains the same: we are building in a decoding pipeline, but now we are using the GStreamer library and glib-events.&lt;/p&gt;

&lt;p&gt;We will consider a live example of H264 decoding.&lt;/p&gt;

&lt;p&gt;Initialization of the GStreamer application takes place once with the help of &lt;code&gt;gst_init (NULL, NULL);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you want to see what’s happening in detail, you can set up a logging level before the initialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gst_debug_set_active(TRUE);
gst_debug_set_default_threshold(GST_LEVEL_LOG);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; no matter how many pipelines you have in your application, it is enough to initialize gst_init once.&lt;/p&gt;

&lt;p&gt;Let’s create a new event-loop where events will be processed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GMainLoop *loop;
loop = g_main_loop_new (NULL, FALSE);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now we can start building our pipeline. Let’s name the necessary elements, in particular, the pipeline itself as the GstElement type :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GstElement *pipeline, *source, *demuxer, *parser, *decoder, *conv, *sink;

pipeline = gst_pipeline_new ("video-decoder");
source   = gst_element_factory_make ("filesrc",       "file-source");
demuxer  = gst_element_factory_make ("qtdemux",      "h264-demuxer");
parser   = gst_element_factory_make ("h264parse",      "h264-parser");
decoder  = gst_element_factory_make ("avdec_h264",     "h264-decoder");
conv     = gst_element_factory_make ("videoconvert",  "converter");
sink     = gst_element_factory_make ("appsink", "video-output");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each element of the pipeline is created via gst_element_factory_make, where the first parameter is the type and the second is its conditional name for GStreamer, on which it will later rely (for example, when issuing errors).&lt;/p&gt;

&lt;p&gt;It would also be nice to check that all components are found otherwise gst_element_factory_make returns NULL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (!pipeline || !source || !demuxer || !parser || !decoder || !conv || !sink) {
    // one element is not initialized - stop
    return;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are setting the same location parameter via g_object_set:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;g_object_set (G_OBJECT (source), "location", argv[1], NULL);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Other parameters in other elements can be set in the same way.&lt;/p&gt;

&lt;p&gt;Now we need the GStreamer message handler, let’s create the corresponding bus_call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GstBus *bus;

guint bus_watch_id;
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;gst_object_unref and other similar calls are needed to clear selected objects.&lt;/p&gt;

&lt;p&gt;Then we will name the message handler itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static gboolean
bus_call (GstBus     *bus,
          GstMessage *msg,
          gpointer    data)
{
  GMainLoop *loop = (GMainLoop *) data;
  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_EOS:
      LOGI ("End of stream\n");
      g_main_loop_quit (loop);
      break;

    case GST_MESSAGE_ERROR: {
      gchar  *debug;
      GError *error;

      gst_message_parse_error (msg, &amp;amp;error, &amp;amp;debug);
      g_free (debug);
      LOGE ("Error: %s\n", error-&amp;gt;message);
      g_error_free (error);
      g_main_loop_quit (loop);
      break;
    }

    default:
      break;
  }
  return TRUE;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now the most important thing: we collect and add all the created elements in a single pipeline, which was built through gst-launch. The order of addition is, of course, important:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gst_bin_add_many (GST_BIN (pipeline), source, demuxer, parser, decoder, conv, sink, NULL);&lt;br&gt;
gst_element_link_many (source, demuxer, parser, decoder, conv, sink, NULL);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We should also note that this linking of elements works perfectly for stream outputs, but in the case of playback (autovideosink) requires additional synchronization and dynamic linking of the demuxer and parser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gst_element_link (source, demuxer);
gst_element_link_many (parser, decoder, conv, sink, NULL);
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), parser);

static void
on_pad_added (GstElement *element,
              GstPad     *pad,
              gpointer    data)
{
  GstPad *sinkpad;
  GstElement *decoder = (GstElement *) data;

  /* We can now link this pad with the sink pad */
  g_print ("Dynamic pad created, linking demuxer/decoder\n");

  sinkpad = gst_element_get_static_pad (decoder, "sink");
  gst_pad_link (pad, sinkpad);
  gst_object_unref (sinkpad);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A dynamic connection makes it possible to determine the type and number of threads in contrast to a static one and will work in some cases when it is required.&lt;/p&gt;

&lt;p&gt;And finally, let’s turn the conveyor status into a playback: &lt;code&gt;gst_element_set_state (pipeline, GST_STATE_PLAYING);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And let’s run event-loop: &lt;code&gt;g_main_loop_run (loop);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After this procedure, everything needs to be cleaned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (pipeline));
g_source_remove (bus_watch_id);
g_main_loop_unref (loop);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Choosing encoders and decoders. Fallbacks.
&lt;/h3&gt;

&lt;p&gt;There’s more to tell about useful but barely mentioned things in the documentation: how you can easily organize a fallback decoder or encoder.&lt;/p&gt;

&lt;p&gt;The gst_element_factory_find function will help us do this by checking if we have a codec in the elements factory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(gst_element_factory_find("omxh264dec"))
  decoder  = gst_element_factory_make ("omxh264dec",     "h264-decoder");
else
  decoder  = gst_element_factory_make ("avdec_h264",     "h264-decoder");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, we have prioritized the selection of an OMX hardware decoder on the RDK platform, and in case of its absence, we will choose a software implementation.&lt;/p&gt;

&lt;p&gt;Another extremely useful but even more rarely used feature is to check what we actually initialized in GstElement (which of many codecs): &lt;code&gt;gst_plugin_feature_get_name(gst_element_get_factory(encoder))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can do it in such a simple way and return the name of the initialized codec.&lt;/p&gt;

&lt;h3&gt;
  
  
  Video color models
&lt;/h3&gt;

&lt;p&gt;We can’t help but mention color models as well since we are talking about encoding video from cameras. And that’s when YUV goes on stage (much more often than RGB).&lt;/p&gt;

&lt;p&gt;Cameras simply love the YUYV color model. But GStreamer likes to work with the usual I420 model much better. If it is not about outputting in the gl-frame, we will also have I420 frames. Get ready to set up the filters you need and perform the transformations.&lt;/p&gt;

&lt;p&gt;Some encoders can work with other color models as well, but more often, these are exceptions to the rule.&lt;/p&gt;

&lt;p&gt;We should also note that GStreamer has its own module for receiving video streams from your camera, and it can be used to build a pipeline, but we will talk about it some other time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let’s deal with buffers and take data on the fly
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Input buffer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s time to deal with the data flows. Until now, we have simply encoded through filesrc what is in the file and displayed everything in the same filesink or on the screen.&lt;/p&gt;

&lt;p&gt;Now we will work with the buffers and the appsrc / appsink inputs and outputs. For some reason, this issue was hardly taken into account in the official documentation.&lt;/p&gt;

&lt;p&gt;So how to organize a constant data flow in the created pipelines, or if to be more precise to the output buffer and get an encoded or decoded output buffer? Let’s say we got the image from the camera and we need to encode it. We have already decided that we need a frame in the I420 format. Let’s say we have it, what’s next? How do I pass a picture through the whole pipeline flow?&lt;/p&gt;

&lt;p&gt;First, let’s set up the need-data event handler, which will be started when it is necessary to feed data into the pipeline and start feeding the input buffer: &lt;code&gt;g_signal_connect (source, "need-data", G_CALLBACK (encoder_cb_need_data), NULL);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The handler itself has the following form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;encoder_cb_need_data (GstElement *appsrc,
                      guint       unused_size,
                      gpointer    user_data)
{
  GstBuffer *buffer;
  GstFlowReturn ret;
  GstMapInfo map;

  int size;
  uint8_t* image;

  // get image
  buffer = gst_buffer_new_allocate (NULL, size, NULL);
  gst_buffer_map (buffer, &amp;amp;map, GST_MAP_WRITE);
  memcpy((guchar *)map.data, image,  gst_buffer_get_size( buffer ) );
  gst_buffer_unmap(buffer, &amp;amp;map);
  g_signal_emit_by_name (appsrc, "push-buffer", buffer, &amp;amp;ret);
  gst_buffer_unref(buffer);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might say that “image” is the pseudo-code of our image buffer in I420.&lt;/p&gt;

&lt;p&gt;Next, we create a buffer of the necessary size through gst_buffer_new_allocate, which will correspond to the size of the image buffer.&lt;/p&gt;

&lt;p&gt;With gst_buffer_map we set the buffer to write mode and use memcpy to copy our image to the created buffer.&lt;/p&gt;

&lt;p&gt;And finally, we signal GStream that the buffer is ready.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; it is essential to use gst_buffer_unmap after writing and to clear the buffer after using gst_buffer_unref. Otherwise, there will be a memory leak. In the low number of available examples, no one was particularly concerned about memory usage, although this is very important.&lt;/p&gt;

&lt;p&gt;Now, when we are done with the handler, one more thing to do is to configure caps on the receipt of our expected format.&lt;/p&gt;

&lt;p&gt;This is done before installing the need-data signal handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;g_object_set (G_OBJECT (source),
              "stream-type", 0,
              "format", GST_FORMAT_TIME, NULL);

g_object_set (G_OBJECT (source), "caps",
              gst_caps_new_simple ("video/x-raw",
                                   "format", G_TYPE_STRING, "I420",
                                   "width", G_TYPE_INT, 640,
                                   "height", G_TYPE_INT, 480,
                                   "framerate", GST_TYPE_FRACTION, 30, 1,
                                   NULL),
              NULL);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like all GstElement parameters, the parameters are set via g_object_set.&lt;/p&gt;

&lt;p&gt;In this case, we have defined the stream type and its caps — the data format. We are specifying that the appsrc output will receive the I420 data with 640×480 resolution and 30 frames per second.&lt;/p&gt;

&lt;p&gt;Frequency in our case, and in general, does not play any role. While working, we haven’t noticed that GStreamer somehow limits need-data calls by frequency.&lt;/p&gt;

&lt;p&gt;Finished, now our frames are fed into the encoder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output buffer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now let’s find out how to get an encoded output stream.&lt;/p&gt;

&lt;p&gt;We connect the handler to the sink pad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GstPad *pad = gst_element_get_static_pad (sink, "sink");
gst_pad_add_probe  (pad, GST_PAD_PROBE_TYPE_BUFFER, encoder_cb_have_data, NULL, NULL);
gst_object_unref (pad);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, we connected to another sink pad event, GST_PAD_PROBE_TYPE_BUFFER, which would be triggered as the data buffer enters the sink pad.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;static GstPadProbeReturn
encoder_cb_have_data (GstPad * pad,
                      GstPadProbeInfo * info,
                      gpointer user_data) {
  GstBuffer *buf = gst_pad_probe_info_get_buffer (info);
  GstMemory *bufMem = gst_buffer_get_memory(buf, 0);
  GstMapInfo bufInfo;

  gst_memory_map(bufMem, &amp;amp;bufInfo, GST_MAP_READ);

  // bufInfo.data, bufInfo.size
  gst_memory_unmap(bufMem, &amp;amp;bufInfo);
  return GST_PAD_PROBE_OK;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The callback has a similar structure. Now, we need to reach the buffer memory. First, we get GstBuffer, then a pointer of its memory using gst_buffer_get_memory by index 0 (as a rule, it is the only one involved). Finally, using gst_memory_map, we get the data buffer address bufInfo.data and its size bufInfo.size.&lt;/p&gt;

&lt;p&gt;In fact, we have achieved the goal of getting a buffer with encoded data and its size. So, we reviewed the key and most exciting components of our Zoom-like video conferencing application for Smart TV and set-top boxes: architecture, encoding/decoding modules with GStreamer, input/output buffers, and color transformations used.&lt;/p&gt;

&lt;p&gt;For digital TV operators, such a software platform can become a new subscriber service. And for us, engineers, this is an interesting new embedded project for implementing different STBs based on RDK, Linux, and Android. As for everybody else, this is an opportunity to spend time together watching movies and sports matches, playing sports, and meeting with loved ones during the COVID-19 quarantine or remote work.&lt;/p&gt;

&lt;p&gt;This idea with video conferencing service on Smart TV can be further developed, both in terms of engineering solutions and business scenarios. So feel free to share your thoughts in the comments below.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>videoconferencing</category>
      <category>smarttv</category>
      <category>appdevelopment</category>
    </item>
    <item>
      <title>Null pointers in C++: what you can and can’t do</title>
      <dc:creator>Ivan Kuten</dc:creator>
      <pubDate>Thu, 30 Jul 2020 12:22:01 +0000</pubDate>
      <link>https://forem.com/ivan_kuten/null-pointers-in-c-what-you-can-and-can-t-do-25ic</link>
      <guid>https://forem.com/ivan_kuten/null-pointers-in-c-what-you-can-and-can-t-do-25ic</guid>
      <description>&lt;p&gt;Some software engineers may have been tired of this topic already, but here we picked 7 examples and tried to explain their behavior using the Standard (the latest draft at the time of writing):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct A {  
int data_mem;  
void non_static_mem_fn() {}  
static void static_mem_fn() {}  
};

void foo(int) {}

A* p{nullptr};

/*1*/ *p;  
/*2*/ foo((*p, 5));  
/*3*/ A a{*p};  
/*4*/ p-&amp;gt;data_mem;  
/*5*/ int b{p-&amp;gt;data_mem};  
/*6*/ p-&amp;gt;non_static_mem_fn();  
/*7*/ p-&amp;gt;static_mem_fn();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One obvious yet important point is that &lt;strong&gt;p&lt;/strong&gt; initialized with a null pointer can’t point to a valid object because it’s “distinguishable from every other value of object pointer” (&lt;a href="http://eel.is/c++draft/conv.ptr#1" rel="noopener noreferrer"&gt;conv.ptr#1&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Example 1&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*p;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s an expression statement with *p being a discarded-value expression which needs to be evaluated nevertheless (&lt;a href="http://eel.is/c++draft/stmt.expr#1" rel="noopener noreferrer"&gt;stmt.expr#1&lt;/a&gt;). By definition (&lt;a href="http://eel.is/c++draft/expr.unary.op#1" rel="noopener noreferrer"&gt;expr.unary.op#1&lt;/a&gt;), the unary operator * “performs indirection,” and the result is “an lvalue referring to the object or function to which the expression points.” It’s clear what semantics is, but not whether there’s a precondition that an object has to exist. A null pointer is not mentioned there even once.&lt;/p&gt;

&lt;p&gt;One could try to conclude from the fact that it performs &lt;em&gt;indirection&lt;/em&gt; because &lt;a href="http://eel.is/c++draft/basic.stc#4" rel="noopener noreferrer"&gt;basic.stc#4&lt;/a&gt; says that &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“indirection through an invalid pointer value . . . have undefined behavior”. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, that exact paragraph contains the definition of an invalid pointer value and refers to &lt;a href="http://eel.is/c++draft/basic.compound#3.4" rel="noopener noreferrer"&gt;basic.compound#3.4&lt;/a&gt;, where a null pointer value and an invalid pointer value are listed as different values of a pointer.&lt;/p&gt;

&lt;p&gt;There’s also a note in &lt;a href="http://eel.is/c++draft/dcl.ref#5" rel="noopener noreferrer"&gt;dcl.ref#5&lt;/a&gt; saying that &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“the only way to create such a reference would be to bind it to the “object” obtained by indirection through a null pointer, which causes undefined behavior,” &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;but it’s not clear which part the last clause is referring to. In case it’s “to bind it,” then binding to a non-existing object is undefined behavior, which goes in line with the normative text of that paragraph.&lt;/p&gt;

&lt;p&gt;Since the Standard leaves room for interpretation instead of being clear on this particular topic, let’s turn to the core language issues list, where the Core Working Group elaborates wording of the Standard, among other things. There’s a dedicated issue for our topic, where CWG came to an informal consensus (that’s how “drafting” status is defined) that  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“&lt;/strong&gt;p = 0; *p; is not inherently an error. An lvalue-to-rvalue conversion would give it undefined behavior.” &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the “informal consensus” doesn’t sound good enough, there’s another &lt;a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#315" rel="noopener noreferrer"&gt;issue&lt;/a&gt; dedicated to example 7, where CWG says it should be allowed for that exact reason.&lt;/p&gt;

&lt;p&gt;I’ll take into account this consensus in what follows. If a future Standard prohibits indirection through a null pointer like C does (&lt;a href="https://web.archive.org/web/20181230041359if_/http:/www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf" rel="noopener noreferrer"&gt;N2176&lt;/a&gt;, 6.5.3.2 and footnote 104), then all examples will be rendered to contain undefined behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Example 2&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foo((*p, 5));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to call &lt;strong&gt;foo()&lt;/strong&gt;&lt;strong&gt;,&lt;/strong&gt; the parameter needs to be initialized, which leads to the evaluation of the operator comma. Its operands are evaluated from left to right, and except for the rightmost, all of them are discarded-value expressions (&lt;a href="http://eel.is/c++draft/expr.comma#1" rel="noopener noreferrer"&gt;expr.comma#1&lt;/a&gt;). So this example is well-formed, too.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Example 3&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A a{*p};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An implicit copy constructor will be picked to initialize &lt;strong&gt;a&lt;/strong&gt;, and &lt;strong&gt;const A&amp;amp;&lt;/strong&gt; needs to be initialized with a valid object in order to call it, otherwise behavior is undefined (&lt;a href="http://eel.is/c++draft/dcl.ref#5" rel="noopener noreferrer"&gt;dcl.ref#5&lt;/a&gt;). However, there’s no such object in our case.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Example 4&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p-&amp;gt;data_mem;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expression of this expression statement will be converted to &lt;strong&gt;(*(p)).data_mem&lt;/strong&gt; per &lt;a href="http://eel.is/c++draft/expr.ref#2" rel="noopener noreferrer"&gt;expr.ref#2&lt;/a&gt;, which &lt;em&gt;designates&lt;/em&gt; “the corresponding member subobject of the object designated by the first expression” (&lt;a href="http://eel.is/c++draft/expr.ref#6.2" rel="noopener noreferrer"&gt;expr.ref#6.2&lt;/a&gt;). It’s once again not clear whether there’s a precondition that an object has to exist. Seeing “to refer” and “to designate” being used interchangeably in &lt;a href="http://eel.is/c++draft/basic.lookup.qual#1" rel="noopener noreferrer"&gt;basic.lookup.qual#1&lt;/a&gt; make it similar to example 1 all the more. I’d say that this example is well-formed because of that, but some compilers disagree. See “Checking with constant expressions” section at the end of this article for more details.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Example 5&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int b{p-&amp;gt;data_mem};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Continuing the previous example, we’ll try to initialize &lt;strong&gt;int&lt;/strong&gt; with the result of expression instead of discarding it. It needs to be converted to prvalue, because expressions of this category initialize objects (&lt;a href="http://eel.is/c++draft/basic.lval#1.2" rel="noopener noreferrer"&gt;basic.lval#1.2&lt;/a&gt;). Since the target type is int, the result of the expression will be accessed (&lt;a href="http://eel.is/c++draft/conv.lval#3.4" rel="noopener noreferrer"&gt;conv.lval#3.4&lt;/a&gt;), which leads to undefined behavior in our case, because none of the conditions in &lt;a href="http://eel.is/c++draft/basic.lval#11" rel="noopener noreferrer"&gt;basic.lval#11&lt;/a&gt; are met.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Example 6&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p-&amp;gt;non_static_mem_fn();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="http://eel.is/c++draft/class.mfct.non-static#1" rel="noopener noreferrer"&gt;class.mfct.non-static#1&lt;/a&gt; reads that &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“a non-static member function may be called for an object of its class type, or for an object of a class derived from its class type,” &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;where “may be” means permission, and not a possibility (&lt;a href="https://www.iso.org/sites/directives/current/part2/index.xhtml#_idTextAnchor082" rel="noopener noreferrer"&gt;ISO Directives Part 2&lt;/a&gt;). So behavior is undefined since there’s no object.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Example 7&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;p-&amp;gt;static_mem_fn();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we mentioned in description to example 1, CWG says that this example is a valid code. The only thing to add is that indirection through expression to the left of -&amp;gt; is performed even when its result is not required (&lt;a href="http://eel.is/c++draft/expr.ref#footnote-59" rel="noopener noreferrer"&gt;foontnote 59&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Checking with constant expressions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Since constant expression can’t rely on undefined behavior (&lt;a href="http://eel.is/c++draft/expr.const#5" rel="noopener noreferrer"&gt;expr.const#5&lt;/a&gt;), we can ask compilers’ opinion on our examples. Even though their diagnostics are not ideal, they are at least sometimes right. We edited our examples a bit to fit them into constant expression evaluation, fed them to three popular compilers, and commented out examples they had considered bad because diagnostic messages of GCC and MSVC leave a lot to be desired on those particular examples. The tests themselves can be found on &lt;a href="https://godbolt.org/z/Mq6oof" rel="noopener noreferrer"&gt;godbolt&lt;/a&gt;, and the summary of our results is presented in the table below.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;

&lt;tbody&gt;

&lt;tr&gt;

&lt;td&gt;

#

&lt;/td&gt;

&lt;td&gt;

Snippet

&lt;/td&gt;

&lt;td&gt;

Expectation

&lt;/td&gt;

&lt;td&gt;

GCC 10.1

&lt;/td&gt;

&lt;td&gt;

Clang 10

&lt;/td&gt;

&lt;td&gt;

MSVC 19.24

&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

1

&lt;/td&gt;

&lt;td&gt;

*p;

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

2

&lt;/td&gt;

&lt;td&gt;

foo((*p, 5));

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

3

&lt;/td&gt;

&lt;td&gt;

A a{*p};

&lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

4

&lt;/td&gt;

&lt;td&gt;

p-&amp;gt;data_mem;

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

5

&lt;/td&gt;

&lt;td&gt;

int b{p-&amp;gt;data_mem};

&lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

6

&lt;/td&gt;

&lt;td&gt;

p-&amp;gt;non_static_mem_fn();

&lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt; &lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;/tr&gt;

&lt;tr&gt;

&lt;td&gt;

7

&lt;/td&gt;

&lt;td&gt;

p-&amp;gt;static_mem_fn();

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;td&gt;

+

&lt;/td&gt;

&lt;/tr&gt;

&lt;/tbody&gt;

&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The results make us a bit doubtful about our conclusion on example 6, and even more on example 4. But it’s also interesting to see all of us share the same opinion about the key example 1.&lt;/p&gt;

&lt;p&gt;Thanks for staying with us to follow the adventures of a null pointer in C++! :-) Usually, we share fragments of code taken from our current &lt;a href="https://promwad.com/services/firmware-development" rel="noopener noreferrer"&gt;firmware development projects&lt;/a&gt;, but this time we were interested in purely "philosophical" questions, so the examples were synthesized.&lt;/p&gt;

&lt;p&gt;If you share our love of contradictions in C++, feel free to share your code and comments.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>programming</category>
      <category>pointers</category>
      <category>coding</category>
    </item>
  </channel>
</rss>
