<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="pretty-atom-feed.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  
  <title>arch1t3cht&#39;s Ramblings</title>
  <subtitle>This is a longer description about your blog.</subtitle>
  <link href="https://arch1t3cht.org/feed/feed.xml" rel="self" />
  <link href="https://arch1t3cht.org/" />
  <updated>2026-04-28T00:00:00Z</updated>
  <id>https://arch1t3cht.org/</id>
  <author>
    <name>arch1t3cht</name>
  </author>
  <entry>
    <title>jjjj</title>
    <link href="https://arch1t3cht.org/blog/jjjj/" />
    <updated>2026-04-28T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/jjjj/</id>
    <content type="html">&lt;p&gt;I saw a blog post about a &lt;a href=&quot;https://www.jj-vcs.dev/&quot;&gt;jujutsu&lt;/a&gt; wrapper called &lt;a href=&quot;https://oppi.li/posts/jjj/&quot;&gt;&lt;code&gt;jjj&lt;/code&gt;&lt;/a&gt; (for &lt;em&gt;jujutsu jump&lt;/em&gt;) today,
and I figured that we couldn&#39;t just stop there.
After all, what if you want to run &lt;code&gt;jjj&lt;/code&gt; on multiple revisions at once?&lt;/p&gt;
&lt;p&gt;Introducing &lt;code&gt;jjjj&lt;/code&gt; (&lt;em&gt;jujutsu jump jobs&lt;/em&gt;):&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token shebang important&quot;&gt;#!/bin/bash&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;cmd&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${1&lt;span class=&quot;token operator&quot;&gt;:-&lt;/span&gt;show}&lt;/span&gt;&quot;&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;selected&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;$(&lt;/span&gt;
  jj log &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;all()&#39;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--color&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;always &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
    &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; fzf &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
        --min-height&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
        &lt;span class=&quot;token parameter variable&quot;&gt;--cycle&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
        &lt;span class=&quot;token parameter variable&quot;&gt;--ansi&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
        &lt;span class=&quot;token parameter variable&quot;&gt;--multi&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;&#92;&lt;/span&gt;
        &lt;span class=&quot;token parameter variable&quot;&gt;--prompt&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jj &lt;span class=&quot;token variable&quot;&gt;$cmd&lt;/span&gt;&gt; &quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;

&lt;span class=&quot;token assign-left variable&quot;&gt;revs&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;echo&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$selected&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;awk&lt;/span&gt; &#39;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;for&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i&lt;span class=&quot;token operator&quot;&gt;&amp;lt;=&lt;/span&gt;NF&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;i++&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; if&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;$i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;print &lt;span class=&quot;token variable&quot;&gt;$i&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; next&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;) #&#39;&lt;/span&gt; have another quote so that the syntax highlighting recovers

&lt;span class=&quot;token comment&quot;&gt;# https://superuser.com/questions/284187/how-to-iterate-over-lines-in-a-variable-in-bash&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token assign-left variable&quot;&gt;&lt;span class=&quot;token environment constant&quot;&gt;IFS&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;read&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; r &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-n&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$r&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;do&lt;/span&gt;
    jj &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$cmd&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-r&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$r&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;${@&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt;2}&lt;/span&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token builtin class-name&quot;&gt;printf&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;%s&#39;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;&lt;span class=&quot;token variable&quot;&gt;$revs&lt;/span&gt;&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This can be run just like &lt;code&gt;jjj&lt;/code&gt;, but now you can select multiple revisions at once using the Tab key and run your &lt;code&gt;jj&lt;/code&gt; command on each of them.&lt;/p&gt;
&lt;p&gt;(By the way, I needed to replace &lt;code&gt;$@&lt;/code&gt; with &lt;code&gt;${@:2}&lt;/code&gt; here and in the original &lt;code&gt;jjj&lt;/code&gt; script to prevent the first argument from being inserted twice.)&lt;/p&gt;
&lt;span style=&quot;font-size: 0.5em; margin-top: 3em&quot;&gt;
Please do not take this too seriously.
&lt;/span&gt;
</content>
  </entry>
  <entry>
    <title>More Falsehoods Programmers Believe About Videos: &quot;IDR Frames are Random Access Points&quot;</title>
    <link href="https://arch1t3cht.org/blog/idr_frames/" />
    <updated>2026-04-19T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/idr_frames/</id>
    <content type="html">&lt;p&gt;The following two links should be mandatory reading/watching for anyone working with videos:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://haasn.dev/posts/2016-12-25-falsehoods-programmers-believe-about-%5Bvideo-stuff%5D.html&quot;&gt;Falsehoods programmers believe about [video stuff]&lt;/a&gt; (&lt;a href=&quot;https://haasn.dev/&quot;&gt;haasn&#39;s blog&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=cRSO3RtUOOk&quot;&gt;Derek Buitenhuis - Things Developers Believe About Video Files (Proven Wrong by User Uploads)&lt;/a&gt; (YouTube)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Today I&#39;d like to talk about another edge case along these lines.
I have encountered&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; it in the wild a couple of times,
and I&#39;ve seen it surprise some fairly experienced developers.
In particular, some of the Common Tools handle this incorrectly in some cases.&lt;/p&gt;
&lt;p&gt;The traditional wisdom is something along the lines of&lt;/p&gt;
&lt;center&gt;
&lt;em&gt;
In H.264, IDR frames flush the decoder&#39;s state,
so it&#39;s safe to start decoding at any IDR frame.
&lt;/em&gt;
&lt;/center&gt;
&lt;p&gt;But this is not actually true!
All an IDR picture&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt; does is flush the &lt;em&gt;decoded picture buffer&lt;/em&gt;
and prevent frames from being reordered around it
(or, more precisely: it marks the all reference pictures as &amp;quot;unused for reference&amp;quot; and resets the picture order count).
But an H.264 decoder has more state than just the decoded picture buffer!&lt;/p&gt;
&lt;p&gt;An H.264 video stream is a sequence of &lt;em&gt;NAL Units&lt;/em&gt; (&lt;em&gt;NAL&lt;/em&gt; being short for &lt;em&gt;Network Abstraction Layer&lt;/em&gt;).
The full list of NAL unit types can be found in ITU-T Rec H.264, Table 7-1, but the most important types are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sequence parameter set (SPS)&lt;/strong&gt;: A structure specifying the format of the coded video sequence.
This includes data like the video&#39;s profile and level, its pixel format, the video&#39;s width and height,
color space information, and various other values signaling which decoding capabilities the stream requires.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Picture parameter set (PPS)&lt;/strong&gt;: A structure signaling more specific information about how pictures are coded.
This includes data like how the picture is split into slices (if any), which entropy coding mode is used,
and the picture&#39;s initial quantization parameter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coded slice of an IDR picture&lt;/strong&gt;: An IDR picture, or one part (slice) of it.
Pictures may be coded as a single slice, or split into multiple slices for e.g. better error resilience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coded slice of a non-IDR picture&lt;/strong&gt;: The same as above for a non-IDR picture.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Supplemental enhancement information (SEI)&lt;/strong&gt;: Additional metadata that may aid in decoding or presentation,
but are not strictly necessary for decoding.
These can include, among many others,
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Picture timing SEI&lt;/strong&gt;: Signaling the frame rate at the bitstream level and possibly applying frame doubling or soft pulldown via a &lt;code&gt;pic_struct&lt;/code&gt; field.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recovery point SEI&lt;/strong&gt;: Signaling from which pictures in the middle of the stream a decoder may start decoding to produce acceptable pictures.
Common wisdom is that these are especially important for open-GOP videos
(i.e. videos that do not contain any IDR pictures, except possibly at the very start,
and instead manually flush reference pictures where applicable.
This allows them to reorder frames around their random access points,
which results in a slight efficiency gain in exchange for causing every multimedia developer headaches.),
but we will see in this post why they can be just as important even when IDR pictures are present.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User data SEI&lt;/strong&gt;: Additional metadata (registered or unregistered) that encoders can freely write.
For example, this is where x264 stores the settings it used to encode the video.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;Various SEIs with extra metadata for players, like scene information, display orientation, HDR metadata, or film grain synthesis.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The data corresponding to a coded picture may hence contain more than one NAL unit.
The collection of NAL units corresponding to a single picture is called an &lt;em&gt;access unit&lt;/em&gt;.
For example, a single packet of an H.264 track in a Matroska file, or a single sample of an H.264 track in an mp4 file,
contains one access unit.&lt;/p&gt;
&lt;p&gt;An H.264 stream may contain more than one SPS or PPS.
Every SPS and PPS has an ID, so that there may be multiple different SPS&#39;s or PPS&#39;s present at the same time.
Every PPS references an SPS by its ID, and every slice of every picture references a PPS.
This is how an SPS and PPS is associated to every slice, which then provides the decoder with the data it needs to decode it.&lt;/p&gt;
&lt;p&gt;Now, what does this imply for IDR pictures and random access points?
Well, it means that a decoder has to store more state across access units than just the reference picture lists (and a couple of numbers like the picture order count)!
It also has to store all parameter sets it encountered while decoding, in case a future PPS or slice references one of them.&lt;/p&gt;
&lt;p&gt;Now, for your &amp;quot;typical&amp;quot;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn4&quot; id=&quot;fnref4&quot;&gt;[4]&lt;/a&gt;&lt;/sup&gt; H.264 file (say, output by x264 with default settings), this is not a problem.
The NAL units of such a file will typically look as follows (assuming, for now, a &lt;em&gt;raw&lt;/em&gt; H.264 bytestream, and not a track muxed into some container file):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Access unit  1: SPS, PPS, x264 version SEI, IDR slice
Access unit  2: non-IDR slice
Access unit  3: non-IDR slice
[...]
Access unit 24: non-IDR slice
Access unit 25: SPS, PPS, IDR slice
Access unit 26: non-IDR slice
[...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is, there is a single SPS and a single PPS (referencing that single SPS) that is repeated before every IDR access unit.
All pictures are coded using a single slice, which references this single PPS.&lt;/p&gt;
&lt;p&gt;When muxing such a stream into a container file like mp4 or mkv, the SPS and PPS will get deduplicated and instead put into the track&#39;s header
(i.e. the &lt;code&gt;stsd&lt;/code&gt; box in mp4 or the &lt;code&gt;CodecPrivate&lt;/code&gt; element in mkv).
A muxed file will hence look as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Track header: SPS, PPS

Access unit  1: x264 version SEI, IDR slice
Access unit  2: non-IDR slice
Access unit  3: non-IDR slice
[...]
Access unit 24: non-IDR slice
Access unit 25: IDR slice
Access unit 26: non-IDR slice
[...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nice and simple.
The SPS and PPS are only stored once, which saves space,
and the decoder can read the parameter sets in the header (and maybe the first frame to find the x264 version) and then jump to any IDR slice and start decoding from there.
Here, all the IDR pictures are beautiful random access points.&lt;/p&gt;
&lt;p&gt;But, of course, it&#39;s never that simple in multimedia.
There&#39;s no requirement for every IDR access unit to contain an SPS or PPS,
and it&#39;s very much possible for an SPS or PPS to change throughout the stream.&lt;/p&gt;
&lt;p&gt;Indeed, the specification says surprisingly little about how parameter sets should be stored or ordered.
Quoting the most important parts of section 7.4.1.2.1, &amp;quot;Order of sequence and picture parameter set RBSPs and their activation&amp;quot;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any picture parameter set NAL unit containing the value of pic_parameter_set_id for the active picture parameter set
RBSP for a coded picture shall have the same content as that of the active picture parameter set RBSP for the coded picture
unless it follows the last VCL NAL unit of the coded picture and precedes the first VCL NAL unit of another coded picture.&lt;/p&gt;
&lt;p&gt;When a picture parameter set NAL unit with a particular value of pic_parameter_set_id is received, its content replaces
the content of the previous picture parameter set NAL unit, in decoding order, with the same value of pic_parameter_set_id
(when a previous picture parameter set NAL unit with the same value of pic_parameter_set_id was present in the
bitstream).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An activated sequence parameter set RBSP shall remain active for the entire coded video sequence.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In slightly more comprehensible English, this means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Only one SPS may be used (i.e. referenced in a PPS which is in turn referenced in a slice) in a coded video sequence.
Here, a &lt;em&gt;coded video sequence&lt;/em&gt; is a sequence of access units from one IDR access units up to but excluding the following IDR access unit.&lt;/li&gt;
&lt;li&gt;There are no contraints on which (or how many) PPS&#39;s are referenced by slices, as long as the referenced IDs exist at all.
If I read the specification correctly, it is even allowed for different slices of the same picture to reference different PPS&#39;s.&lt;/li&gt;
&lt;li&gt;In general it is allowed for two different SPS&#39;s or PPS&#39;s to have the same ID, in which case the newer parameter set simply replaces the old one.
However, for PPS&#39;s this must not happen in the &lt;em&gt;middle&lt;/em&gt; of a picture (e.g. between two slices), while for SPS&#39;s it may not happen in the middle of a coded video sequence.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In particular, the following are all allowed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An IDR frame that is not preceded by an SPS or PPS in the same access unit&lt;/li&gt;
&lt;li&gt;A slice referencing a parameter set that was last signaled 10,000 frames ago&lt;/li&gt;
&lt;li&gt;A bunch of different PPS&#39;s all having the same ID and hence repeatedly overriding each other&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this in mind, there&#39;s no way all IDR pictures can be random access points!
When starting decoding at some IDR picture in the middle of the stream,
there is no guarantee that all the subsequently needed parameter sets are included in this IDR access unit.&lt;/p&gt;
&lt;p&gt;In fact, a search through the specification shows that this is not all that surprising.
There is absolutely no mention of IDR access units being random access points or recovery points.
Random access and/or recovery points are only mentioned in relation to recovery point SEIs (more on those later).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Now, okay, we&#39;ve established that some H.264 streams may be weird enough that IDR frames do not work as random access points.
But surely no such weird files actually exist in practice, right?
And if they do, that&#39;s still fine, because after remuxing we can just put all the parameter sets in the header, right?
Right?&lt;/p&gt;
&lt;p&gt;Of course, this is multimedia, so the answer is no.
Specifically, I have seen multiple Blu-rays&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn5&quot; id=&quot;fnref5&quot;&gt;[5]&lt;/a&gt;&lt;/sup&gt; containing m2ts video streams where&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are multiple different PPS&#39;s, all having the same ID of 0&lt;/li&gt;
&lt;li&gt;These PPS&#39;s have different initial quantization parameters&lt;/li&gt;
&lt;li&gt;Not every IDR frame is preceded by a PPS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If, for such a stream, you seek to one of the IDR frames not preceded by a PPS while the decoder&#39;s stored PPS with ID 0 is not the PPS with ID 0 that actually precedes this IDR frame,
the decoder uses the wrong initial quantization parameter and very bad things happen (i.e. CABAC breaks and the output is completely corrupted).
So, indeed, not all IDR frames of these (perfectly legal, as far as I can tell!) files are random access points.&lt;/p&gt;
&lt;p&gt;This concludes discussing the &amp;quot;Falsehood&amp;quot; in the post&#39;s title, but there are still two interesting questions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;How can a media player or source filter&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn6&quot; id=&quot;fnref6&quot;&gt;[6]&lt;/a&gt;&lt;/sup&gt; handle such a file?&lt;/li&gt;
&lt;li&gt;How can such a file be &amp;quot;fixed&amp;quot; when remuxing it into a better container format like mkv?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Of course, the answer to the first question will depend on the player&#39;s or source filter&#39;s architecture.
For example, bestsource can simply seek to any IDR frame it finds and try to decode from there.
If the IDR frame&#39;s packet does not contain an access unit, the decoder will get corrupted frames back which it will hence drop.
At some point the decoder will reach an IDR frame which &lt;em&gt;does&lt;/em&gt; contain a PPS, and will return an intact frame to bestsource.
Bestsource can then compare the hash of this frame to the index of hashed frames it computed from a linear decode beforehand,
notice that they do not match, and hence blacklist the IDR frame it seeked to and try again from an earlier seek point.
So, like the vast majority of other files, bestsource will handle such a file completely fine.
(But, as always, this reliability comes at the cost of a much longer indexing time, and slightly slower decoding due to needing to hash every frame.)&lt;/p&gt;
&lt;p&gt;FFMS2, on the other hand, is not so lucky.
FFMS2 does not run a full decode when indexing the file, and instead only demuxes and parses every packet&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn7&quot; id=&quot;fnref7&quot;&gt;[7]&lt;/a&gt;&lt;/sup&gt;.
As such, it has no way of knowing which IDR frames contain parameter sets and which don&#39;t.
In theory, it could inspect the timestamps of the &lt;code&gt;AVFrame&lt;/code&gt;s the decoder spits out and try to guess at whether or not it dropped any packets,
but this sounds quite brittle and may be hard to distinguish from frames being (correctly) dropped around non-IDR recovery points in open-GOP videos.&lt;/p&gt;
&lt;p&gt;Similarly, media players usually do not do any initial indexing at all, so they will have the same problems FFMS2 does.
And, indeed, opening such an m2ts file in mpv results in corrupted output on some seeks.&lt;/p&gt;
&lt;p&gt;And, really, the conceptual issue here lies not in FFMS2 or mpv, but in FFmpeg itself.
Indeed, the video streams in question do in fact contain recovery point SEI messages that correctly signal which IDR frames are actual random access points.
So a hypothetical ideal source filter could scan the file for such SEI messages while indexing, and then use the corresponding packets as seek points.
But, unfortunately, FFmpeg simply marks every IDR frame in H.264 as a keyframe and offers no way to tell whether a keyframe flag came from a recovery point SEI or from the packet containing an IDR slice.&lt;/p&gt;
&lt;p&gt;As such, one could argue that FFmpeg precisely falls for the Falsehood discussed here.
But making FFmpeg not mark IDR frames as keyframes is probably not an option either, since H.264 streams are in no way required to contain recovery point SEIs
(and, indeed, closed-GOP x264 encodes do not contain any by default).
So the presence recovery point SEIs would have to be communicated to the FFmpeg user in some other way, and I&#39;m not yet sure what the best method for that would be.&lt;/p&gt;
&lt;p&gt;The second question is also tricky.
If all the different PPS&#39;s had different IDs, they could simply all be included in the file&#39;s header,
but since they all have the ID 0, this is not possible.
As far as I can see, there are three options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Patch the bitstream to give all of these parameter sets different IDs and update the references to the parameter sets accordingly,
then add all the parameter sets in the header.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Not mark IDR access units that do not contain the required parameter sets as keyframes in the resulting container.&lt;/p&gt;
&lt;p&gt;This would result in a &amp;quot;correct&amp;quot; file, but it wouldn&#39;t actually help FFmpeg-based filters and players:
When demuxing a file, ffmpeg will also parse the resulting packets and update its flags accordingly.
With its current behavior, when it sees an H.264 packet containing an IDR slice, it will set the packet&#39;s &lt;code&gt;AV_PKT_FLAG_KEY&lt;/code&gt;,
even if the packet was not marked as a keyframe in the container.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Insert additional copies of the parameter sets to ensure that every IDR access unit contains the parameter sets it needs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The third option is the one that mkvtoolnix uses.
Hence, if you encounter such a file, you can remux it using mkvtoolnix to &amp;quot;fix&amp;quot; it
(that is, make it easier for players and source filters to seek accurately inside it).
In fact, if you really want to, you could even mux the video back to an m2ts afterwards.
But you really shouldn&#39;t.&lt;/p&gt;
&lt;p&gt;FFmpeg and MakeMKV, on the other hand, do not do any special handling for this at all&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn8&quot; id=&quot;fnref8&quot;&gt;[8]&lt;/a&gt;&lt;/sup&gt; when remuxing.
As such, remuxing such an m2ts file with one of these tools will result in an mkv file that has packets marked as keyframes that are not actually random access points,
which violates the Matroska specification.&lt;/p&gt;
&lt;p&gt;Unfortunately, it doesn&#39;t seem possible to fix an existing mkv file that is &amp;quot;broken&amp;quot; in this way with a direct mkvtoolnix remux.
Instead, the video needs to be demuxed and muxed from scratch again,
which results in additional headaches when the video track has other metadata (frame rates, DAR, track flags, etc) that may get lost during a demux and remux.&lt;/p&gt;
&lt;p&gt;In conclusion, video is hard and everything is broken. What&#39;s new.&lt;/p&gt;
&lt;p&gt;If I got anything about this wrong, please comment and let me know.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Update, two hours later&lt;/em&gt;: Ridley points out that FFmpeg does actually have a bitstream filter &lt;a href=&quot;https://ffmpeg.org/ffmpeg-all.html#h264_005fredundant_005fpps&quot;&gt;h264_redundant_pps&lt;/a&gt;
that is designed to fix precisely the sort of Blu-ray streams described above.
(I know for a fact that I looked for FFmpeg BSFs to fix these streams back when I initially investigated this,
but I must have missed this one or forgotten about it.)&lt;/p&gt;
&lt;p&gt;Hence, you can fix such a file using e.g. &lt;code&gt;ffmpeg -i foo.mkv -c copy -bsf:v h264_redundant_pps out.mkv&lt;/code&gt;,
give or take some extra &lt;code&gt;-map&lt;/code&gt; arguments to actually copy all streams.&lt;/p&gt;
&lt;p&gt;Specifically, this filter will set the &lt;code&gt;pic_init_qp_minus26&lt;/code&gt; of every PPS to 0 (and &lt;code&gt;weighted_pred_flag&lt;/code&gt; to 1)
and adjust the &lt;code&gt;slice_qp_delta&lt;/code&gt; of all slices to match.
This is enough to make all the differing PPS&#39;s of these types of Blu-ray streams agree, but of course it may not work for a general file.&lt;/p&gt;
&lt;p&gt;And, in fact, the plot thickens further:
FFmpeg&#39;s m2ts muxer actually does &lt;a href=&quot;https://code.ffmpeg.org/FFmpeg/FFmpeg/src/commit/5e69e6d49c95ebe8e31849b28cea16894fd23e2e/libavformat/mpegtsenc.c#L1920-L1971&quot;&gt;insert copies of the parameter sets before every IDR picture&lt;/a&gt;.
After all, it &lt;em&gt;needs&lt;/em&gt; to do this when muxing from an mp4 or mkv file where the parameter sets are only stored in the header.
m2ts files are transport streams and thus have no such &amp;quot;header&amp;quot;, so the parameter sets need to be inserted back into the actual access units.&lt;/p&gt;
&lt;p&gt;Unfortunately, the muxer does this incorrectly in the harder cases:
Instead of scanning through the stream and keeping track of what the last stored parameter sets were,
it simply inserts the parameter sets contained in the header (i.e. the &lt;code&gt;extradata&lt;/code&gt;) into every IDR access unit that does not already contain parameter sets.
For the Blu-ray streams above, where there exist multiple different parameter sets with the same ID,
this means that the resulting m2ts files may not simply be &lt;em&gt;missing&lt;/em&gt; parameter sets before some IDR frames, but have the &lt;em&gt;wrong&lt;/em&gt; parameter sets in some IDR access units.
That is, the resulting streams will not just be hard to seek in, but be genuinely broken.&lt;/p&gt;
&lt;p&gt;I guess I&#39;ll see if I can open some bug reports and/or try to fix some of these issues.&lt;/p&gt;
&lt;p&gt;As a summary of the current situation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Not all IDR frames are random access points.
There is no easy way &lt;em&gt;in general&lt;/em&gt; to determine which IDR frames in a raw H.264 stream or m2ts file are random access points&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn9&quot; id=&quot;fnref9&quot;&gt;[9]&lt;/a&gt;&lt;/sup&gt;,
but &amp;quot;If there are recovery point SEIs, rely on those, and fall back to &#39;all IDR frames&#39; otherwise&amp;quot; should work for most cases in the wild.
However, ffmpeg provides no way to distinguish between SEI recovery points and IDR frames, so players and source filters will struggle on such streams.&lt;/p&gt;
&lt;p&gt;The following points will go into detail about how such files can be made easier to seek in with further processing,
but none of them will improve this situation for players or source filters on the &lt;em&gt;original&lt;/em&gt; streams.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;em&gt;general&lt;/em&gt; H.264 stream can have very pathological orders of parameter sets.
However, the only case I have so far heard of or encountered in the wild are Blu-ray streams that have parameter sets differing only in &lt;code&gt;pic_init_qp_minus26&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some container formats like mp4 (but &lt;em&gt;not&lt;/em&gt; m2ts) may have additional restrictions on the order of parameter sets, so streams in those may be better behaved.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A remux using mkvtoolnix will fix&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn10&quot; id=&quot;fnref10&quot;&gt;[10]&lt;/a&gt;&lt;/sup&gt; the parameter set ordering of any stream when remuxing from a format different from mkv.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A remux to mkv using FFmpeg (with no additional BSFs) or MakeMKV will &lt;em&gt;not&lt;/em&gt; fix the parameter set ordering, and thus result in files where some packets marked as keyframes are not actually random access points.
However, such files can still be fixed with further remuxing.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The specific case of the Blu-ray streams described above can be fixed using FFmpeg&#39;s &lt;code&gt;h264_redundant_pps&lt;/code&gt; BSF.
This works in any container, i.e. both in m2ts files (or even raw h264 files) &lt;em&gt;and&lt;/em&gt; in mkv files, even if they have incorrect keyframe flags.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Remuxing one of the Blu-ray streams described above to m2ts using FFmpeg will result in a &lt;strong&gt;broken&lt;/strong&gt; m2ts file that cannot be fixed.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For somebody running into such a Blu-ray stream, the current advice is hence to remux it using mkvtoolnix and/or to run it through the &lt;code&gt;h264_redundant_pps&lt;/code&gt; BSF.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Next update, two days later&lt;/em&gt;:
And, of course, that&#39;s still not everything.
FFmpeg also has &lt;em&gt;another&lt;/em&gt; bitstream filter called &lt;code&gt;h264_mp4toannexb&lt;/code&gt; that will convert a stream of NAL units in the format that an mp4 or mkv file expects (with a length field for every NAL unit) into the format used in raw .h264 bytestreams or m2ts files (with NAL units being separated by start codes as in Annex B of the H.264 specification).
Apart from converting length fields to start codes, this BSF will also insert copies of the parameter sets before the IDR access units, similarly to what mkvtoolnix does.
Unlike the m2ts muxer, which simply inserts the possibly incorrect parameter sets from the extradata, &lt;code&gt;h264_mp4toannnexb&lt;/code&gt; does properly scan the stream for parameter sets and remembers the most recent paramter sets found in the stream&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fn11&quot; id=&quot;fnref11&quot;&gt;[11]&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;...Except that &lt;code&gt;h264_mp4toannexb&lt;/code&gt; also does not fully work.
More precisely, at the time of writing it fails to insert parameter sets when there are multiple &lt;em&gt;consecutive&lt;/em&gt; IDR access units, since it only inserts the parameter sets at most once for every sequence of NAL units with no non-IDR slices in between.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;h264_mp4toannexb&lt;/code&gt; BSF is automatically inserted when remuxing from an mp4-style container to an Annex B-style container, but not when the input is already in Annex B-format (and it cannot be manually inserted in that case either).
So a remux from mp4 or mkv to m2ts will run this BSF, while a remux from m2ts to m2ts will not.
So what I wrote in the last update remains valid - in particular a remux from m2ts to m2ts will result in a broken file when the input has multiple different parameter sets with the same ID.
However, an FFmpeg remux from m2ts to mkv, followed by a remux from mkv to m2ts will result in an intact file that just happens to still have some IDR access units without parameter sets.&lt;/p&gt;
&lt;p&gt;But why doesn&#39;t the m2ts muxer then insert the extradata&#39;s parameter sets into those access units, you might ask?
Because, for some reason, the m2ts muxer still gets its extradata in mp4 format rather than its Annex B-format, even though it ran the &lt;code&gt;h264_mp4toannexb&lt;/code&gt; BSF.
So it will not add the extradata in this case since it has the wrong format.
Why is the extradata still in mp4 format even though the BSF converted it?
Who knows.
This is probably not supposed to be the case, even if it does prevent breaking the output here.&lt;/p&gt;
&lt;p&gt;Throw a rock, hit three FFmpeg bugs.&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Meaning, &amp;quot;Someone else encountered a file breaking their source filter and sent it to me to investigate.&amp;quot; &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;From now on I&#39;ll follow H.264&#39;s terminology and use the term &lt;em&gt;picture&lt;/em&gt; rather than &lt;em&gt;frame&lt;/em&gt;.
A &lt;em&gt;picture&lt;/em&gt; is either a frame, or a single field of a frame in an interlaced video encoded field-by-field. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;A tangentially related fun fact:
The x264 version SEI actually affects decoding in FFmpeg,
since FFmpeg has several code paths that check what version (if any) of x264 produced a stream
and apply special handling for bugs in old x264 versions producing slightly incorrect files.&lt;/p&gt;
&lt;p&gt;Most notably, before x264 version 151, x264 would output broken streams when encoding in 4:4:4 chroma,
and FFmpeg would decode them in an equally incorrect way, resulting in a &amp;quot;correct&amp;quot; decode.
Both FFmpeg and x264 were &lt;a href=&quot;https://code.FFmpeg.org/FFmpeg/FFmpeg/commit/840b41b2a643fc8f0617c0370125a19c02c6b586&quot;&gt;fixed&lt;/a&gt;,
but many broken files produced by x264 still existed in the wild,
so FFmpeg checks the signaled x264 version and falls back to its old, &amp;quot;incorrect&amp;quot;, decoding behavior when it sees an x264 version older than 151 on 4:4:4 video.&lt;/p&gt;
&lt;p&gt;This has the fun (?) consequence that source filters and media players always need to start by decoding a video&#39;s first frame,
even if they intend to seek to the middle of the stream,
since otherwise FFmpeg&#39;s decoder will not find the x264 version. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn4&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&amp;quot;typical&amp;quot; being in quotes here because, of course, there&#39;s no such thing. A better word might be &amp;quot;naive&amp;quot;. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref4&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn5&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;The files I (or other people asking me) have encountered were from the Blu-rays for the following shows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WataMote&lt;/li&gt;
&lt;li&gt;Ping Pong the Animation&lt;/li&gt;
&lt;li&gt;Lord Marksman and Vanadis&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is probably not a complete list. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref5&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn6&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;By &lt;em&gt;source filter&lt;/em&gt; I mean a tool (say, a library or a VapourSynth plugin) like &lt;a href=&quot;https://github.com/FFMS/ffms2&quot;&gt;FFMS2&lt;/a&gt; or &lt;a href=&quot;https://github.com/vapoursynth/bestsource&quot;&gt;Bestsource&lt;/a&gt; that,
usually after scanning the file and creating some sort of index,
provides an API to accurately and reliably obtain any frame in the file given its frame number.
As we have seen, videos can be very complicated, so writing a correct and fast source filter is anywhere from very hard to impossible, depending on the formats one wants to support. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref6&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn7&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;&lt;em&gt;Parsing&lt;/em&gt; here means using FFmpeg&#39;s &lt;code&gt;av_parser_parse2&lt;/code&gt; to get some additional metadata about every packet, &lt;em&gt;not&lt;/em&gt; manually parsing every packet of every format itself. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref7&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn8&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;And while writing this I now realize that I never made an actual bug report about this to either of those two programs, and now I feel bad.
I do generally make an effort to report all the bugs I find, since I do very much dislike the practice of complaining about bugs on random discord servers without ever reporting them,
but sometimes I still forget - especially when it&#39;s a bug that doesn&#39;t affect me personally and that I just found because someone asked me why their video file is broken.
I&#39;ll see if I can make a bug report soon, I guess.
At the very least, it&#39;s hopefully clear that I am writing about this because it&#39;s an interesting and educational story, not because I want to complain about any of these tools. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref8&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn9&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Where &amp;quot;easy&amp;quot; means &amp;quot;without indexing the entire stream and parsing all parameter sets and slice headers.&amp;quot; &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref9&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn10&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Where &amp;quot;fix&amp;quot; means &amp;quot;output an mkv file where every IDR frame is a random access point.&amp;quot; &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref10&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn11&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;It doesn&#39;t actually remember the parameter sets by their &lt;em&gt;ID&lt;/em&gt;, and instead just remembers the set of parameter sets found in the last packet that contained &lt;em&gt;any&lt;/em&gt; parameter sets, but this works in all reasonable cases. &lt;a href=&quot;https://arch1t3cht.org/blog/idr_frames/#fnref11&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
  <entry>
    <title>Hi Hello this Site Exists Now</title>
    <link href="https://arch1t3cht.org/blog/newblog/" />
    <updated>2026-04-15T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/newblog/</id>
    <content type="html">&lt;p&gt;Until now, I tried to avoid having a dedicated blog because :effort:, but&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The various pages and guides I&#39;ve written are distributed across&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;My &lt;a href=&quot;https://gist.github.com/arch1t3cht&quot;&gt;GitHub gists&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/tree/arch.Perspective-v1.2.1/doc&quot;&gt;One of my GitHub repositories&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/&quot;&gt;JET Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The &lt;a href=&quot;https://fansubbers.miraheze.org/&quot;&gt;Fansubbing Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Pins in various Discord servers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This was getting a bit too insane even for me.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;GitHub has kind of been going to shit recently&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/newblog/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt; so I felt like I should maybe prepare to put my stuff elsewhere.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;From time to time I feel like writing something and ask myself where to put it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Ryan tells me I need to have &amp;quot;a based blog with random insane posts on it&amp;quot; to truly be torch v2.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, here we are.
I&#39;m not yet sure what to do with my existing guides, so for now I just made posts here linking to wherever the guides are currently hosted.
That way, there&#39;s at least a single page listing all of my relevant guides.
Maybe I&#39;ll move some of them to this page eventually.&lt;/p&gt;
&lt;p&gt;Will this actually make me write more, or will it stay half-finished like half of my other projects?
Stay tuned and find out!&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Well, even more now than before, at least. &lt;a href=&quot;https://arch1t3cht.org/blog/newblog/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
  <entry>
    <title>What Every Typesetter Should Know about Renderer Internals</title>
    <link href="https://arch1t3cht.org/blog/renderer_internals/" />
    <updated>2025-12-29T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/renderer_internals/</id>
    <content type="html">&lt;p&gt;After popular demand, I wrote a guide explaining how the libass subtitle renderer works internally,
and what implications this has on the performance of different subtitle effects.&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://gist.github.com/arch1t3cht/8cb1793beb72d30e334c7c46ff8c1080&quot;&gt;https://gist.github.com/arch1t3cht/8cb1793beb72d30e334c7c46ff8c1080&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>What you NEED to Know Before Touching a Video File</title>
    <link href="https://arch1t3cht.org/blog/video_noob_guide/" />
    <updated>2025-05-27T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/video_noob_guide/</id>
    <content type="html">&lt;p&gt;I wrote a guide explaining most of the basics of multimedia, in particular video encoding and remuxing,
in order to try and help new users to avoid some of the many rookie mistakes one can make when it comes to working with videos.&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://gist.github.com/arch1t3cht/b5b9552633567fa7658deee5aec60453&quot;&gt;https://gist.github.com/arch1t3cht/b5b9552633567fa7658deee5aec60453&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Karaoke Templater Idioms, Snippets, and Tricks</title>
    <link href="https://arch1t3cht.org/blog/templaters_idioms/" />
    <updated>2024-12-15T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/templaters_idioms/</id>
    <content type="html">&lt;p&gt;A supplement or sequel to my &lt;a href=&quot;https://arch1t3cht.org/blog/templaters/&quot;&gt;karaoke templater guide&lt;/a&gt; listing various snippets and idioms for more advanced karaoke templater usage.&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/blob/main/doc/templaters_idioms.md&quot;&gt;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/blob/main/doc/templaters_idioms.md&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The JET Guide</title>
    <link href="https://arch1t3cht.org/blog/jet_guide/" />
    <updated>2024-05-08T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/jet_guide/</id>
    <content type="html">&lt;p&gt;There have been multiple attempts (&lt;a href=&quot;https://guide.encode.moe/&quot;&gt;guide.encode.moe&lt;/a&gt; and &lt;a href=&quot;https://silentaperture.gitlab.io/mdbook-guide/introduction.html&quot;&gt;the silentaperture guide&lt;/a&gt;&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/#fn1&quot; id=&quot;fnref1&quot;&gt;[1]&lt;/a&gt;&lt;/sup&gt;) at making a guide for modern anime encoding in the past,
but none of them was ever completed, and the existing guides got more and more outdated as time went on and encoding practices evolved.
I threw my own hat in the ring myself with my &lt;a href=&quot;https://arch1t3cht.org/blog/resources/&quot;&gt;encoding resources gist&lt;/a&gt;, but of course that, too, was a long way from an actual guide.&lt;/p&gt;
&lt;p&gt;After the topic of starting another guide project had come up a couple of times in IEW&#39;s and later JET&#39;s chat&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/#fn2&quot; id=&quot;fnref2&quot;&gt;[2]&lt;/a&gt;&lt;/sup&gt;,
I eventually just spun up an mdbook guide repository and moved my encoding resources gist to it.
My reasoning being that it&#39;s better to at least have &lt;em&gt;some&lt;/em&gt; info available online, no matter how incomplete or badly structured,
than to spend months privately working on the perfect guide that never ends up being published.&lt;/p&gt;
&lt;p&gt;Moreover, trying to learn from the problems that the old encode.moe guide had (where contributions were not reviewed or merged for a long time, which resulted in the project dying out),
I adopted a very liberal contribution policy, stating that any and all contributions would be merged fairly quickly provided that they are factually correct and remotely intelligible
(even if they were, say, incomplete or redundant with other pages).
I&#39;m one of the biggest defenders of bikeshedding in the contexts where it matters (namely, when backwards compatibility is relevant or where precedents are being set for the future),
but when it comes to simply collecting information, the slogans &amp;quot;Perfect is the enemy of good&amp;quot; and &amp;quot;Just make it exist first, you can make it good later&amp;quot; definitely apply.&lt;/p&gt;
&lt;p&gt;It&#39;s been two years since then, so, did this work?
Well, the guide still has much less content than I&#39;d like it to have.
Which, of course, I myself am just as much to blame for as anyone else since I also haven&#39;t contributed too much content.
My biggest pages, the descale guide and the page on codecs and containers are still unfinished, and many other pages I&#39;d like to write one day haven&#39;t even been started yet.
The guide is also fairly poorly structured overall - some content is redundant and the formatting and structure is wildly inconsistent between the pages.&lt;/p&gt;
&lt;p&gt;But this was exactly what I signed up for with this policy.
The bottom line is that this content is now available online &lt;em&gt;at all&lt;/em&gt;,
instead of only floating around in various Discord servers.
Having a poorly structured guide is better than not having one at all.
And maybe one day I&#39;ll finish all of the pages I started.
Writing good guides is hard.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/#fn3&quot; id=&quot;fnref3&quot;&gt;[3]&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: To clarify, I am of course not solely responsible for the JET guide.
I&#39;m the person who kicked off the project and wrote the first few pages,
but big parts of its content have since been written by other people (thanks!).&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://jaded-encoding-thaumaturgy.github.io/JET-guide/master/&quot;&gt;https://jaded-encoding-thaumaturgy.github.io/JET-guide/master/&lt;/a&gt;&lt;/p&gt;
&lt;hr class=&quot;footnotes-sep&quot;&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn1&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Not to mention several &lt;em&gt;additional&lt;/em&gt; started projects that never made it far enough to be released publicly. &lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/#fnref1&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn2&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;While a Certain Person whose name shall not be named kept insisting that they were working on their own guide, which they will definitely release next weekend!
Needless to say, that guide has still not been released even today (in 2026). &lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/#fnref2&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;fn3&quot; class=&quot;footnote-item&quot;&gt;&lt;p&gt;Which, incidentally, I might write something about soon, too. &lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/#fnref3&quot; class=&quot;footnote-backref&quot;&gt;↩︎&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
  <entry>
    <title>Encoding Resources</title>
    <link href="https://arch1t3cht.org/blog/resources/" />
    <updated>2023-12-14T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/resources/</id>
    <content type="html">&lt;p&gt;As my first attempt for an encoding guide, I wrote a page collecting all the various encoding-related resources I found useful when learning about the subject.
This then eventually grew into the &lt;a href=&quot;https://arch1t3cht.org/blog/jet_guide/&quot;&gt;JET guide&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Original Link: &lt;a href=&quot;https://gist.github.com/arch1t3cht/ef5ec3fe0e2e8ae58fcbae903f32cfe5&quot;&gt;https://gist.github.com/arch1t3cht/ef5ec3fe0e2e8ae58fcbae903f32cfe5&lt;/a&gt;
&lt;br&gt;
Current Link: &lt;a href=&quot;https://jaded-encoding-thaumaturgy.github.io/JET-guide/master/resources/&quot;&gt;https://jaded-encoding-thaumaturgy.github.io/JET-guide/master/resources/&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Miscellaneous Tricks with Karaoke Templaters</title>
    <link href="https://arch1t3cht.org/blog/misc_kara/" />
    <updated>2022-11-15T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/misc_kara/</id>
    <content type="html">&lt;p&gt;A supplement to my &lt;a href=&quot;https://arch1t3cht.org/blog/templaters/&quot;&gt;karaoke templater guide&lt;/a&gt; explaining some uses of karaoke templaters outside of actual karaoke and dissecting the thought process behind writing them.
Some of the code examples are a bit outdated now that better libraries (in particular ILL) are available, but the general concepts are still relevant.&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/blob/main/doc/misc_kara.md&quot;&gt;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/blob/main/doc/misc_kara.md&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The Math Behind Perspective in .ass Subtitles</title>
    <link href="https://arch1t3cht.org/blog/perspectivemath/" />
    <updated>2022-08-11T00:00:00Z</updated>
    <id>https://arch1t3cht.org/blog/perspectivemath/</id>
    <content type="html">&lt;p&gt;I&#39;ll be honest, I completely forgot about this page and only rediscovered it now when going through all my old ramblings so I could link them on this blog.
I don&#39;t think anything in there is &lt;em&gt;wrong&lt;/em&gt;, but it&#39;s fairly outdated at this point.
(It was written after I got Zahuczky&#39;s old Perspective-Motion script to work correctly, but before I built Aegisub&#39;s built-in perspective tool or my own improved PerspectiveMotion script.)
Still, I&#39;ll link it here for completeness.&lt;/p&gt;
&lt;p&gt;If you&#39;re interested in the math behind the new perspective tools,
I tried my best to structure and comment the code of both &lt;a href=&quot;https://github.com/arch1t3cht/Aegisub/blob/168b6f679db0cd3f622aa76e77fb2703e2766537/src/visual_tool_perspective.cpp#L574-L872&quot;&gt;Aegisub&#39;s built-in perspective tool&lt;/a&gt;
and &lt;a href=&quot;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/blob/44ab7cd2fc72e52bfad96cf2b2b20284031c51d3/modules/arch/Perspective.moon#L208-L380&quot;&gt;my Perspective.moon module used in the perspective scripts&lt;/a&gt;
as well as possible, so you should hopefully be able to read those for more insights.&lt;/p&gt;
&lt;p&gt;Link: &lt;a href=&quot;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/blob/main/doc/perspective_math.md&quot;&gt;https://github.com/TypesettingTools/arch1t3cht-Aegisub-Scripts/blob/main/doc/perspective_math.md&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
</feed>