Skip to content

Commit 38ec752

Browse files
committed
Custom error codes for jsfetch
1 parent 06dee92 commit 38ec752

File tree

7 files changed

+91
-15
lines changed

7 files changed

+91
-15
lines changed

dist/libav-6.5.7.1-h264-aac-mp3.wasm.mjs

Lines changed: 2 additions & 2 deletions
Large diffs are not rendered by default.
124 Bytes
Binary file not shown.

ffmpeg-7.1/fftools/ffmpeg.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,18 @@ int main(int argc, char **argv)
10521052
sch_free(&sch);
10531053

10541054
#ifdef __EMSCRIPTEN__
1055+
int jsfetch_return_code = jsfetch_get_return_code();
1056+
// Aborted
1057+
if (ret == 255) {
1058+
exit(ret);
1059+
}
1060+
// There are some code paths that retry, so only return a jsfetch_return_code
1061+
// if there is a ret code.
1062+
// For example, hls.c can retry segment and manifest fetches.
1063+
// This avoids returning a jsfetch_return_code when we're successful.
1064+
if (ret && jsfetch_return_code) {
1065+
exit(jsfetch_return_code);
1066+
}
10551067
exit(ret);
10561068
#endif
10571069
return ret;

ffmpeg-7.1/libavformat/jsfetch.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,22 @@ static const AVClass jsfetch_context_class = {
4747
.version = LIBAVUTIL_VERSION_INT
4848
};
4949

50+
/**
51+
* Get return code
52+
*
53+
* 100-600: Reserved for HTTP (i.e 403, 500)
54+
* 1001: Network Error
55+
* 1002: Read Error
56+
*/
57+
EM_JS(int, jsfetch_get_code, (), {
58+
return Module.returnCode || 0;
59+
});
60+
61+
int jsfetch_get_return_code()
62+
{
63+
return jsfetch_get_code();
64+
}
65+
5066
EM_JS(void, jsfetch_abort, (), {
5167
var abortController = Module.abortController;
5268
if (abortController) {
@@ -136,6 +152,11 @@ EM_JS(int, jsfetch_open_js, (const char* url, char* range_header, bool has_range
136152
return -0x54584945; /* AVERROR_EXIT*/
137153
}
138154
if (response instanceof Error) {
155+
if (response.status) {
156+
Module.returnCode = response.status;
157+
} else {
158+
Module.returnCode = 1001; /* Network Error*/
159+
}
139160
// Should return a partial file if we've downloaded anything so far.
140161
return -0x20464f45 /* AVERROR_EOF */;
141162
}
@@ -346,6 +367,7 @@ EM_JS(int, jsfetch_read_js, (int idx, unsigned char *toBuf, int size), {
346367
}
347368

348369
// Otherwise, there was an error
370+
Module.returnCode = 1002; /* Read Error*/
349371
Module.fsThrownError = rej;
350372
console.error(rej);
351373
return -11 /* ECANCELED */;

ffmpeg-7.1/libavformat/jsfetch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
#define JSFETCH_H
33

44
void jsfetch_abort_request(void);
5+
int jsfetch_get_return_code(void);
56

67
#endif

patches/ffmpeg/07-jsfetch-protocol.diff

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -406,18 +406,20 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
406406
===================================================================
407407
--- /dev/null
408408
+++ ffmpeg-6.0.1/libavformat/jsfetch.h
409-
@@ -0,0 +1,6 @@
409+
@@ -0,0 +1,7 @@
410410
+#ifndef JSFETCH_H
411411
+#define JSFETCH_H
412412
+
413413
+void jsfetch_abort_request(void);
414+
+int jsfetch_get_return_code(void);
414415
+
415416
+#endif
417+
416418
Index: ffmpeg-6.0.1/libavformat/jsfetch.c
417419
===================================================================
418420
--- /dev/null
419421
+++ ffmpeg-6.0.1/libavformat/jsfetch.c
420-
@@ -0,0 +1,458 @@
422+
@@ -0,0 +1,485 @@
421423
+/*
422424
+ * JavaScript fetch metaprotocol for ffmpeg client
423425
+ * Copyright (c) 2023 Yahweasel and contributors
@@ -467,10 +469,28 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
467469
+ .version = LIBAVUTIL_VERSION_INT
468470
+};
469471
+
472+
+/**
473+
+ * Get return code
474+
+ *
475+
+ * 100-600: Reserved for HTTP (i.e 403, 500)
476+
+ * 1001: Network Error
477+
+ * 1002: Read Error
478+
+ */
479+
+EM_JS(int, jsfetch_get_code, (), {
480+
+ return Module.returnCode || 0;
481+
+});
482+
+
483+
+int jsfetch_get_return_code()
484+
+{
485+
+ return jsfetch_get_code();
486+
+}
487+
+
470488
+EM_JS(void, jsfetch_abort, (), {
471-
+ var abortController = Module.libavjsJSFetch.abortController;
489+
+ var abortController = Module.abortController;
472490
+ if (abortController) {
473491
+ abortController.abort();
492+
+ } else {
493+
+ Module.abortController = new AbortController()
474494
+ }
475495
+});
476496
+
@@ -484,7 +504,10 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
484504
+EM_JS(int, jsfetch_open_js, (const char* url, char* range_header, bool has_range, int force_idx, bool enable_retries), {
485505
+ return Asyncify.handleAsync(function() {
486506
+ if (!Module.libavjsJSFetch)
487-
+ Module.libavjsJSFetch = {ctr: 1, fetches: {}, abortController: new AbortController()};
507+
+ Module.libavjsJSFetch = {ctr: 1, fetches: {}};
508+
+ if (!Module.abortController) {
509+
+ Module.abortController = new AbortController()
510+
+ }
488511
+ return Promise.all([]).then(function() {
489512
+ url = UTF8ToString(url);
490513
+ var headers = {};
@@ -496,7 +519,7 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
496519
+
497520
+ // Retry function with exponential backoff
498521
+ function fetchWithRetry(retryCount) {
499-
+ return fetch(fetchUrl, { headers, signal: Module.libavjsJSFetch.abortController.signal }).then(function(response) {
522+
+ return fetch(fetchUrl, { headers, signal: Module.abortController.signal }).then(function(response) {
500523
+ // Check for HTTP errors (4xx/5xx status codes)
501524
+ if (!response.ok) {
502525
+ var error = new Error('HTTP Error: ' + response.status + ' ' + response.statusText);
@@ -523,7 +546,7 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
523546
+ var delay = Math.pow(2, retryCount) * 250;
524547
+ return new Promise(function(resolve) {
525548
+ let timeoutId = setTimeout(resolve, delay);
526-
+ Module.libavjsJSFetch.abortController.signal.addEventListener('abort', () => {
549+
+ Module.abortController.signal.addEventListener('abort', () => {
527550
+ clearTimeout(timeoutId);
528551
+ resolve();
529552
+ error.aborted = true
@@ -551,6 +574,11 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
551574
+ return -0x54584945; /* AVERROR_EXIT*/
552575
+ }
553576
+ if (response instanceof Error) {
577+
+ if (response.status) {
578+
+ Module.returnCode = response.status;
579+
+ } else {
580+
+ Module.returnCode = 1001; /* Network Error*/
581+
+ }
554582
+ // Should return a partial file if we've downloaded anything so far.
555583
+ return -0x20464f45 /* AVERROR_EOF */;
556584
+ }
@@ -708,7 +736,7 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
708736
+ return -1;
709737
+ }
710738
+ return Asyncify.handleAsync(function() { return Promise.all([]).then(function() {
711-
+ if (Module.libavjsJSFetch.abortController.signal.aborted) {
739+
+ if (Module.abortController.signal.aborted) {
712740
+ return -0x54584945; /* AVERROR_EXIT*/
713741
+ }
714742
+ if (jsfo.buf || jsfo.rej) {
@@ -761,6 +789,7 @@ Index: ffmpeg-6.0.1/libavformat/hls.c
761789
+ }
762790
+
763791
+ // Otherwise, there was an error
792+
+ Module.returnCode = 1002; /* Read Error*/
764793
+ Module.fsThrownError = rej;
765794
+ console.error(rej);
766795
+ return -11 /* ECANCELED */;

patches/ffmpeg/08-fftools.diff

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Index: ffmpeg-7.1/fftools/ffmpeg.c
22
===================================================================
33
--- ffmpeg-7.1.orig/fftools/ffmpeg.c
44
+++ ffmpeg-7.1/fftools/ffmpeg.c
5-
@@ -316,22 +316,29 @@ static void ffmpeg_cleanup(int ret)
5+
@@ -316,22 +316,29 @@
66
for (int i = 0; i < nb_filtergraphs; i++)
77
fg_free(&filtergraphs[i]);
88
av_freep(&filtergraphs);
@@ -32,7 +32,7 @@ Index: ffmpeg-7.1/fftools/ffmpeg.c
3232
}
3333
av_freep(&vstats_filename);
3434
of_enc_stats_close();
35-
@@ -544,6 +551,19 @@ void update_benchmark(const char *fmt, ...)
35+
@@ -544,6 +551,19 @@
3636
current_time = t;
3737
}
3838
}
@@ -52,7 +52,7 @@ Index: ffmpeg-7.1/fftools/ffmpeg.c
5252

5353
static void print_report(int is_last_report, int64_t timer_start, int64_t cur_time, int64_t pts)
5454
{
55-
@@ -645,6 +665,9 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
55+
@@ -645,6 +665,9 @@
5656

5757
if (total_size < 0) av_bprintf(&buf_script, "total_size=N/A\n");
5858
else av_bprintf(&buf_script, "total_size=%"PRId64"\n", total_size);
@@ -62,15 +62,15 @@ Index: ffmpeg-7.1/fftools/ffmpeg.c
6262
if (pts == AV_NOPTS_VALUE) {
6363
av_bprintf(&buf_script, "out_time_us=N/A\n");
6464
av_bprintf(&buf_script, "out_time_ms=N/A\n");
65-
@@ -654,6 +677,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
65+
@@ -654,6 +677,7 @@
6666
av_bprintf(&buf_script, "out_time_ms=%"PRId64"\n", pts);
6767
av_bprintf(&buf_script, "out_time=%s%02"PRId64":%02d:%02d.%06d\n",
6868
hours_sign, hours, mins, secs, us);
6969
+ curr_transcode_pts_ms = (pts / 1000);
7070
}
7171

7272
if (nb_frames_dup || nb_frames_drop)
73-
@@ -943,7 +967,21 @@ static int64_t getmaxrss(void)
73+
@@ -943,7 +967,21 @@
7474
#endif
7575
}
7676

@@ -92,7 +92,7 @@ Index: ffmpeg-7.1/fftools/ffmpeg.c
9292
{
9393
Scheduler *sch = NULL;
9494

95-
@@ -1009,8 +1047,12 @@ finish:
95+
@@ -1009,8 +1047,24 @@
9696
ret = 0;
9797

9898
ffmpeg_cleanup(ret);
@@ -101,6 +101,18 @@ Index: ffmpeg-7.1/fftools/ffmpeg.c
101101
sch_free(&sch);
102102

103103
+#ifdef __EMSCRIPTEN__
104+
+ int jsfetch_return_code = jsfetch_get_return_code();
105+
+ // Aborted
106+
+ if (ret == 255) {
107+
+ exit(ret);
108+
+ }
109+
+ // There are some code paths that retry, so only return a jsfetch_return_code
110+
+ // if there is a ret code.
111+
+ // For example, hls.c can retry segment and manifest fetches.
112+
+ // This avoids returning a jsfetch_return_code when we're successful.
113+
+ if (ret && jsfetch_return_code) {
114+
+ exit(jsfetch_return_code);
115+
+ }
104116
+ exit(ret);
105117
+#endif
106118
return ret;

0 commit comments

Comments
 (0)