{"id":3210,"date":"2011-03-17T21:53:23","date_gmt":"2011-03-18T04:53:23","guid":{"rendered":"http:\/\/multimedia.cx\/eggs\/?p=3210"},"modified":"2011-03-17T22:04:47","modified_gmt":"2011-03-18T05:04:47","slug":"roq-on-dreamcast","status":"publish","type":"post","link":"https:\/\/multimedia.cx\/eggs\/roq-on-dreamcast\/","title":{"rendered":"RoQ on Dreamcast"},"content":{"rendered":"<p>I have been working on that challenge to play back video on the Sega Dreamcast. To review, <a href=\"http:\/\/multimedia.cx\/eggs\/playing-video-on-a-sega-dreamcast\/\">I asserted that the RoQ format would be a good fit for the Sega Dreamcast<\/a> hardware. The goal was to play 640&#215;480 video at 30 frames\/second. Short version: I have determined that <strong>it is possible to decode such video in real time<\/strong>. However, I ran into certain data rate caveats.<\/p>\n<p>First off: Have you ever wondered if the Dreamcast can read an 80mm optical disc? It can! I discovered this when I only had 60 MB of RoQ samples to burn on a disc and a spindle full of these 210MB-capacity 80mm CD-Rs that I never have occasion to use.<\/p>\n<p><center><br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2011\/03\/dreamcast-80mm-disc.jpg\" alt=\"\" title=\"The Sega Dreamcast can read 80mm CD-Rs\" width=\"400\" height=\"196\" class=\"aligncenter size-full wp-image-3212\" srcset=\"https:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2011\/03\/dreamcast-80mm-disc.jpg 400w, https:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2011\/03\/dreamcast-80mm-disc-300x147.jpg 300w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><br \/>\n<\/center><\/p>\n<p><strong>New RoQ Library<\/strong><br \/>\nThere are open source RoQ decoders out there but I decided to write a new one. A few reasons: 1) RoQ is so simple that I didn&#8217;t think it would take too long; 2) it would be nice to have a RoQ library that is license-compatible (BSD-like) with the rest of the KallistiOS distribution; 3) the idroq.tar.gz distribution, while license-compatible, has enough issues that I didn&#8217;t want to correct it.<\/p>\n<p>Thankfully, I was correct about the task not being too difficult: I put together a new RoQ decoder in short order. I&#8217;m a bit embarrassed to admit that the part I had the most trouble with was properly converting YUV -> RGB.<br \/>\n<!--more--><br \/>\nAbout the approach I took: While the original idroq.tar.gz decoder maintains YUV 4:2:0 codebooks (which led to chroma bugs during motion compensation) and FFmpeg&#8217;s decoder maintains YUV 4:4:4 codebooks, this decoder is built to convert the YUV 4:2:0 vectors into RGB565 vectors during the vector unpacking phase. Thus, the entire frame is rendered in RGB565 &#8212; no lengthy YUV -> RGB conversion after decoding &#8212; and all pixels are shuffled around as 16-bit units (minor speedup vs. shuffling everything as bytes).<\/p>\n<p>I also entertained the idea of maintaining YUYV codebooks (since the DC supports that colorspace as a texture format). But I scrapped that idea when I remembered it would lead to the same chroma bleeding problem seen in the original idroq.tar.gz decoder.<\/p>\n<p><strong>Onto The Dreamcast<\/strong><br \/>\nI developed the library on a Linux computer, allowing it to output a series of PNM files for visual verification and debugging. Dropping it into a basic DC\/KOS-compatible program was trivial and the first order of business was profiling.<\/p>\n<p>At first, I profiled the entire decode operation: open file, then read and decode each chunk while tossing away the results. I was roundly disappointed to see that, e.g., an 8.5-second RoQ sample needed a little more than 20 seconds to complete. Not real time. I performed a series of optimizations on the decoding library that netted notable performance gains when profiling on Linux. When I brought these same optimizations over to the DC, decoding time didn&#8217;t improve at all. This was my first suspicion that perhaps my assumptions regarding the DC&#8217;s optical drive&#8217;s data rate were not correct.<\/p>\n<p><strong>Dreamcast Data Rate Profiling<\/strong><br \/>\nLet&#8217;s start with some definitions: In terms of data rate, an &#8216;X&#8217;, i.e., 1X is the minimum data rate needed to read CD quality audio from a disc. At that speed, a drive should be able to stream 75 sectors each second. When reading mode 1\/form 1 CD-ROM data, each sector has 2048 bytes (2 kbytes), so a single-speed data rate should achieve 150 kbytes\/sec.<\/p>\n<p>The Dreamcast is supposed to possess a 12X optical drive. This would imply a maximum data rate of 150 kbytes\/sec * 12 = 1800 kbytes\/sec.<\/p>\n<p>Rigging up a trivial experiment using the RoQ samples burned on a few different CD-R discs, the best data rate I can see is about 500-525 kbytes\/sec, or around 3.5X.<\/p>\n<p>Where&#8217;s the discrepancy? My first theory has to do with the fact that not all optical media is created equal. This is why optical drives often advertise a slew of numbers which refer to the best theoretical speed for reading a CD vs. writing a CD-R vs. writing a CD-RW, etc. Perhaps the DC drive can&#8217;t read CD-Rs very quickly. To test this theory, I tried streaming a large file from a conventionally mastered CD-ROM. This worked well for the closest CD-ROM I had on hand: I was able to stream data at a rate that works out to about 6.5X.<\/p>\n<p><em>I smell a science project for another evening: Profiling read speeds from a mastered CD-ROM, burned CD-R, and also a mastered GD-ROM, on each of the 3 Dreamcast consoles I possess (I&#8217;ve heard that there&#8217;s variance between optical drives depending on manufacturing run).<\/em><\/p>\n<p><strong>The Good News<\/strong><br \/>\nI added a little finer-grained code to profile just the video decoding functions. The good news is that the decoder meets my real time goals: That 8.5-second RoQ sample encoded at 640x480x30fps makes its way through the video decoding functions on the DC in a little less than 5 seconds. If the optical drive can supply the data fast enough, the video decoder can take care of the rest.<\/p>\n<p>The RoQ encoder included with FFmpeg does not honor any bitrate parameters. Instead, I encoded the same file at 320&#215;240. It reportedly decoded in real time and can be streamed in real time as well.<\/p>\n<p>I say &#8220;reportedly&#8221; because I&#8217;m simply working from textual output at this point; the next phase is to hook the decoder up to the display hardware.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>High resolution RoQ video can be decoded in real time in a Sega Dreamcast; but can it be streamed in real time?<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[221],"tags":[],"class_list":["post-3210","post","type-post","status-publish","format-standard","hentry","category-sega-dreamcast"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/3210","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/comments?post=3210"}],"version-history":[{"count":7,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/3210\/revisions"}],"predecessor-version":[{"id":3218,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/3210\/revisions\/3218"}],"wp:attachment":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/media?parent=3210"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/categories?post=3210"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/tags?post=3210"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}