Skip to content

Commit b7cce3d

Browse files
committed
fix ffmpeg4 constructed wrong avcc for videotoolbox
1 parent ba5d3aa commit b7cce3d

File tree

2 files changed

+122
-59
lines changed

2 files changed

+122
-59
lines changed

patches/ffmpeg-n4.0/0012-fix-ffmpeg-constructed-wrong-avcc-for-videotoolbox-h.patch

Lines changed: 0 additions & 59 deletions
This file was deleted.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
From e662624b224ae76d275e2628664e6c91ded296c1 Mon Sep 17 00:00:00 2001
2+
From: qianlongxu <qianlongxu@gmail.com>
3+
Date: Tue, 10 Jun 2025 18:24:40 +0800
4+
Subject: [PATCH 12] fix ffmpeg4 constructed wrong avcc for videotoolbox
5+
6+
---
7+
libavcodec/h264_ps.c | 4 +++
8+
libavcodec/videotoolbox.c | 61 ++++++++++++++++++++++++++++++++++-----
9+
2 files changed, 57 insertions(+), 8 deletions(-)
10+
11+
diff --git a/libavcodec/h264_ps.c b/libavcodec/h264_ps.c
12+
index 15fb8b6..8cdb93c 100644
13+
--- a/libavcodec/h264_ps.c
14+
+++ b/libavcodec/h264_ps.c
15+
@@ -752,6 +752,10 @@ int ff_h264_decode_picture_parameter_set(GetBitContext *gb, AVCodecContext *avct
16+
}
17+
memcpy(pps->data, gb->buffer, pps->data_size);
18+
19+
+ // Re-add the removed stop bit (may be used by hwaccels).
20+
+ if (!(bit_length & 7) && pps->data_size < sizeof(pps->data))
21+
+ pps->data[pps->data_size++] = 0x80;
22+
+
23+
pps->sps_id = get_ue_golomb_31(gb);
24+
if ((unsigned)pps->sps_id >= MAX_SPS_COUNT ||
25+
!ps->sps_list[pps->sps_id]) {
26+
diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
27+
index 57b6698..064efe0 100644
28+
--- a/libavcodec/videotoolbox.c
29+
+++ b/libavcodec/videotoolbox.c
30+
@@ -118,14 +118,49 @@ int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
31+
32+
#define AV_W8(p, v) *(p) = (v)
33+
34+
+static int escape_ps(uint8_t* dst, const uint8_t* src, int src_size)
35+
+{
36+
+ int i;
37+
+ int size = src_size;
38+
+ uint8_t* p = dst;
39+
+
40+
+ for (i = 0; i < src_size; i++) {
41+
+ if (i + 2 < src_size &&
42+
+ src[i] == 0x00 &&
43+
+ src[i + 1] == 0x00 &&
44+
+ src[i + 2] <= 0x03) {
45+
+ if (dst) {
46+
+ *p++ = src[i++];
47+
+ *p++ = src[i];
48+
+ *p++ = 0x03;
49+
+ } else {
50+
+ i++;
51+
+ }
52+
+ size++;
53+
+ } else if (dst)
54+
+ *p++ = src[i];
55+
+ }
56+
+
57+
+ if (dst)
58+
+ av_assert0((p - dst) == size);
59+
+
60+
+ return size;
61+
+}
62+
+
63+
CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
64+
{
65+
VTContext *vtctx = avctx->internal->hwaccel_priv_data;
66+
H264Context *h = avctx->priv_data;
67+
CFDataRef data = NULL;
68+
uint8_t *p;
69+
- int vt_extradata_size = 6 + 2 + h->ps.sps->data_size + 3 + h->ps.pps->data_size;
70+
- uint8_t *vt_extradata = av_malloc(vt_extradata_size);
71+
+ int sps_size = escape_ps(NULL, h->ps.sps->data, h->ps.sps->data_size);
72+
+ int pps_size = escape_ps(NULL, h->ps.pps->data, h->ps.pps->data_size);
73+
+ int vt_extradata_size;
74+
+ uint8_t *vt_extradata;
75+
+
76+
+ vt_extradata_size = 6 + 2 + sps_size + 3 + pps_size;
77+
+ vt_extradata = av_malloc(vt_extradata_size);
78+
+
79+
if (!vt_extradata)
80+
return NULL;
81+
82+
@@ -137,14 +172,14 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
83+
AV_W8(p + 3, h->ps.sps->data[3]); /* level */
84+
AV_W8(p + 4, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 3 (11) */
85+
AV_W8(p + 5, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
86+
- AV_WB16(p + 6, h->ps.sps->data_size);
87+
- memcpy(p + 8, h->ps.sps->data, h->ps.sps->data_size);
88+
- p += 8 + h->ps.sps->data_size;
89+
+ AV_WB16(p + 6, sps_size);
90+
+ p += 8;
91+
+ p += escape_ps(p, h->ps.sps->data, h->ps.sps->data_size);
92+
AV_W8(p + 0, 1); /* number of pps */
93+
- AV_WB16(p + 1, h->ps.pps->data_size);
94+
- memcpy(p + 3, h->ps.pps->data, h->ps.pps->data_size);
95+
+ AV_WB16(p + 1, pps_size);
96+
+ p += 3;
97+
+ p += escape_ps(p, h->ps.pps->data, h->ps.pps->data_size);
98+
99+
- p += 3 + h->ps.pps->data_size;
100+
av_assert0(p - vt_extradata == vt_extradata_size);
101+
102+
// save sps header (profile/level) used to create decoder session,
103+
@@ -152,6 +187,16 @@ CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
104+
if (vtctx)
105+
memcpy(vtctx->sps, h->ps.sps->data + 1, 3);
106+
107+
+// {
108+
+// char buffer[128];
109+
+// sprintf(buffer, "%s", "\nnew avcc:");
110+
+// int len = (int)strlen(buffer);
111+
+// for (int i = 0; i < vt_extradata_size; i++) {
112+
+// len += sprintf(buffer + len, "%02x", avctx->extradata[i]);
113+
+// }
114+
+// av_log(avctx, AV_LOG_INFO, "%s\n", buffer);
115+
+// }
116+
+
117+
data = CFDataCreate(kCFAllocatorDefault, vt_extradata, vt_extradata_size);
118+
av_free(vt_extradata);
119+
return data;
120+
--
121+
2.39.5 (Apple Git-154)
122+

0 commit comments

Comments
 (0)