Skip to content

Commit d312b20

Browse files
committed
jo_MPEG update
1 parent 36f2858 commit d312b20

File tree

6 files changed

+36
-11
lines changed

6 files changed

+36
-11
lines changed

posts/jo-mpeg-in-c/comparison.png

504 KB
Loading
494 KB
Loading

posts/jo-mpeg-in-c/jo-mpeg-in-c.md

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,46 @@
22
title: Jo_MPEG converted to C
33
permalink: "/{{ page.fileSlug }}/"
44
date: 2022-02-18
5-
last_modified:
5+
last_modified: 2024-08-15
66
description: Single-header MPEG-1 Video library ported to C
77
publicTags:
88
- C++
99
- C
1010
- video
1111
image: jo_mpeg.png
1212
---
13-
jo_mpeg is a C++ [single header library](https://github.com/nothings/single_file_libs) written by [Jon Olick](https://www.jonolick.com/home/mpeg-video-writer), which creates MPEG-1 videos (without audio). It is [listed as a C++ only library](https://github.com/nothings/single_file_libs#video) in stb's single header library collection. However, only the & reference format is what makes this library C++ only. Replacing those with simple pointers makes this compile with both C and C++: [jo_mpeg.h](jo_mpeg.h)
14-
15-
( I also found this: https://github.com/yui0/slibs/blob/master/jo_mpeg.h, but it is one version behind. )
13+
jo_mpeg is a C++ [single header library](https://github.com/nothings/single_file_libs) written by [Jon Olick](https://www.jonolick.com/home/mpeg-video-writer), which creates MPEG-1 videos (without audio). It is [listed as a C++ only library](https://github.com/nothings/single_file_libs#video) in stb's single header library collection. However, only the & reference format is what makes this library C++ only. Replacing those with simple pointers makes this compile with both C and C++.
1614

1715
<details>
1816
<summary>Full source of the C compatible <a href="jo_mpeg.h">jo_mpeg.h</a></summary>
1917

2018
```c
2119
{% rawFile "posts/jo-mpeg-in-c/jo_mpeg.h" %}
2220
```
23-
</details>
21+
</details>
22+
23+
## Results
24+
I encoded a couple of seconds from [Big Buck Bunny](https://peach.blender.org/) as a sample: [sample.mpg](sample.mpg).
25+
26+
<blockquote class="reaction"><div class="reaction_text">Can't show it directly in browser, as MPEG1 is not supported anymore. Also there is <a href="https://jsmpeg.com/">jsmpeg</a>, but it also doesn't support this output.</div><img class="kiwi" src="/assets/kiwis/facepalm.svg"></blockquote>
27+
28+
<figure>
29+
<img src="comparison.png" alt="Input frame vs Output frame. Side effect of conversion: Increased saturation and contrast." />
30+
<figcaption>Input frame vs Output frame. Side effect of conversion: Increased saturation and contrast.</figcaption>
31+
</figure>
32+
33+
Unfortunately, the output has increased saturation and contrast. This is due to RGB -> [YCbCr](https://en.wikipedia.org/wiki/YCbCr#RGB_conversion) conversion in line `230` - `232` scaling the final color vectors scaled too much. I fixed this by reverting the color space math changes that happened with the update to `v1.02`.
34+
35+
<figure>
36+
<img src="comparisonNew.png" alt="Input frame vs Output frame. Reverted to old color math." />
37+
<figcaption>Input frame vs Output frame. Reverted to old color math.</figcaption>
38+
</figure>
39+
40+
I'm not sure why the code change credited to `r- lyeh` happened, but I guess the used video player handled color space incorrectly. Both [VLC](https://www.videolan.org/) and [MPV](https://mpv.io/) playback the colors correctly with `v1.03`.
41+
42+
Quality is hardcoded and results in roughly `8mbps` at a resolution of `684x385`. Quality measurements are at roughly `27db` [PSNR](https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio#Quality_estimation_with_PSNR) and `0.9` [SSIM](https://medium.com/srm-mic/all-about-structural-similarity-index-ssim-theory-code-in-pytorch-6551b455541e)...
43+
44+
<figure>
45+
<video width="684" height="342" controls><source src="not-terrible.mp4" type="video/mp4"></video>
46+
<figcaption>...Or in other words</figcaption>
47+
</figure>

posts/jo-mpeg-in-c/jo_mpeg.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/* public domain Simple, Minimalistic, No Allocations MPEG writer - http://jonolick.com
22
*
3-
* "Converted" to C by Wladislav Artsimovich
4-
* I just added a bunch of * and removed a bunch of & ¯\_(ツ)_/¯
3+
* Converted to C by Wladislav Artsimovich https://blog.frost.kiwi/jo-mpeg-in-c
54
*
65
* Latest revisions:
6+
* 1.03 (15-08-2024) Reverted color space change from 1.02, as it resulted in
7+
* overscaled color vectors and thus oversaturated colors
78
* 1.02 (22-03-2017) Fixed AC encoding bug.
89
* Fixed color space bug (thx r- lyeh!)
910
* 1.01 (18-10-2016) warning fixes
@@ -25,7 +26,7 @@
2526
* Movie players *should* support it as the spec allows it, but ...
2627
*
2728
* MPEG-1/2 currently has no active patents as far as I am aware.
28-
*
29+
*
2930
* http://dvd.sourceforge.net/dvdinfo/mpeghdrs.html
3031
* http://www.cs.cornell.edu/dali/api/mpegvideo-c.html
3132
* */
@@ -227,9 +228,9 @@ void jo_write_mpeg(FILE *fp, const unsigned char *rgbx, int width, int height, i
227228
y = y >= height ? height-1 : y;
228229
const unsigned char *c = rgbx + y*width*4+x*4;
229230
float r = c[0], g = c[1], b = c[2];
230-
Y[i] = (0.299f*r + 0.587f*g + 0.114f*b) * (219.f/255) + 16;
231-
CBx[i] = (-0.299f*r - 0.587f*g + 0.886f*b) * (224.f/255) + 128;
232-
CRx[i] = (0.701f*r - 0.587f*g - 0.114f*b) * (224.f/255) + 128;
231+
Y[i] = (0.59f*r + 0.30f*g + 0.11f*b) * (219.f/255) + 16;
232+
CBx[i] = (-0.17f*r - 0.33f*g + 0.50f*b) * (224.f/255) + 128;
233+
CRx[i] = (0.50f*r - 0.42f*g - 0.08f*b) * (224.f/255) + 128;
233234
}
234235

235236
// Downsample Cb,Cr (420 format)
360 KB
Binary file not shown.

posts/jo-mpeg-in-c/sample.mpeg

10.3 MB
Binary file not shown.

0 commit comments

Comments
 (0)