Skip to content

Commit cb460b2

Browse files
authored
Merge pull request #29 from bilibili/fix/tags-memory-leak
fix: memory leak caused by tags
2 parents 040adeb + cea1094 commit cb460b2

File tree

2 files changed

+80
-57
lines changed

2 files changed

+80
-57
lines changed

lib/web-demuxer/post.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,6 @@ class WorkerFile {
101101

102102
function avStreamToObject(avStream) {
103103
const extradata = new Uint8Array(avStream.extradata);
104-
const tags = {};
105-
106-
for(let i = 0; i < avStream.tags.size(); i++) {
107-
const { key, value } = avStream.tags.get(i);
108-
tags[key] = value;
109-
}
110-
111104
const result = {
112105
id: avStream.id,
113106
index: avStream.index,
@@ -138,7 +131,7 @@ function avStreamToObject(avStream) {
138131
duration: avStream.duration,
139132
rotation: avStream.rotation,
140133
nb_frames: avStream.nb_frames,
141-
tags
134+
tags: avStream.tags
142135
};
143136

144137
avStream.delete();

lib/web-demuxer/web_demuxer.cpp

Lines changed: 79 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -36,33 +36,42 @@ typedef struct WebAVStream
3636
std::string codec_name;
3737
std::string codec_string;
3838
std::string profile;
39-
std::string pix_fmt;
40-
std::string color_primaries;
41-
std::string color_transfer;
42-
std::string color_space;
43-
std::string color_range;
4439
int level;
45-
int width;
46-
int height;
47-
int channels;
48-
int sample_rate;
49-
std::string sample_fmt;
5040
std::string bit_rate;
5141
int extradata_size;
5242
std::vector<uint8_t> extradata;
5343
val get_extradata() const{
5444
return val(typed_memory_view(extradata.size(), extradata.data()));
5545
}
56-
/** Other Info */
46+
/** Video-specific Info */
47+
int width;
48+
int height;
49+
std::string pix_fmt;
50+
std::string color_primaries;
51+
std::string color_transfer;
52+
std::string color_space;
53+
std::string color_range;
5754
std::string r_frame_rate;
5855
std::string avg_frame_rate;
5956
std::string sample_aspect_ratio;
6057
std::string display_aspect_ratio;
58+
double rotation;
59+
/** Audio-specific Info */
60+
int channels;
61+
int sample_rate;
62+
std::string sample_fmt;
63+
/** Other Common Info */
6164
double start_time;
6265
double duration;
63-
double rotation;
6466
std::string nb_frames;
6567
std::vector<Tag> tags;
68+
val get_tags() const {
69+
val tags = val::object();
70+
for (const Tag &tag : this->tags) {
71+
tags.set(tag.key, tag.value);
72+
}
73+
return tags;
74+
}
6675
} WebAVStream;
6776

6877
typedef struct WebAVPacket
@@ -124,6 +133,10 @@ std::string gen_rational_str(AVRational rational, char sep)
124133
return oss.str();
125134
}
126135

136+
inline std::string safe_str(const char* str) {
137+
return str ? str : "";
138+
}
139+
127140
void gen_web_packet(WebAVPacket &web_packet, AVPacket *packet, AVStream *stream)
128141
{
129142
double packet_timestamp = packet->pts * av_q2d(stream->time_base);
@@ -147,41 +160,77 @@ void gen_web_stream(WebAVStream &web_stream, AVStream *stream, AVFormatContext *
147160
web_stream.index = stream->index;
148161
web_stream.id = stream->id;
149162

150-
// codecpar info
163+
// Initialize codec info
151164
AVCodecParameters *par = stream->codecpar;
152165
web_stream.codec_type = (int)par->codec_type;
153-
web_stream.codec_type_string = av_get_media_type_string(par->codec_type);
154-
web_stream.codec_name = avcodec_descriptor_get(par->codec_id)->name;
166+
web_stream.codec_type_string = safe_str(av_get_media_type_string(par->codec_type));
167+
168+
const AVCodecDescriptor* desc = avcodec_descriptor_get(par->codec_id);
169+
web_stream.codec_name = safe_str(desc ? desc->name : "");
170+
171+
// Initialize video-specific values
172+
web_stream.width = 0;
173+
web_stream.height = 0;
174+
web_stream.color_primaries = "";
175+
web_stream.color_transfer = "";
176+
web_stream.color_space = "";
177+
web_stream.color_range = "";
178+
web_stream.pix_fmt = "";
179+
web_stream.r_frame_rate = "0/0";
180+
web_stream.avg_frame_rate = "0/0";
181+
web_stream.rotation = 0;
182+
web_stream.sample_aspect_ratio = "N/A";
183+
web_stream.display_aspect_ratio = "N/A";
184+
// Initialize audio-specific values
185+
web_stream.channels = 0;
186+
web_stream.sample_rate = 0;
187+
web_stream.sample_fmt = "";
155188

156189
char codec_string[40];
157190

158191
if (par->codec_type == AVMEDIA_TYPE_VIDEO)
159192
{
160-
web_stream.color_primaries = av_color_primaries_name(par->color_primaries);
161-
web_stream.color_transfer = av_color_transfer_name(par->color_trc);
162-
web_stream.color_space = av_color_space_name(par->color_space);
163-
web_stream.color_range = av_color_range_name(par->color_range);
193+
// Video-specific properties
194+
web_stream.width = par->width;
195+
web_stream.height = par->height;
196+
web_stream.color_primaries = safe_str(av_color_primaries_name(par->color_primaries));
197+
web_stream.color_transfer = safe_str(av_color_transfer_name(par->color_trc));
198+
web_stream.color_space = safe_str(av_color_space_name(par->color_space));
199+
web_stream.color_range = safe_str(av_color_range_name(par->color_range));
200+
web_stream.pix_fmt = safe_str(av_get_pix_fmt_name((AVPixelFormat)par->format));
201+
web_stream.r_frame_rate = gen_rational_str(stream->r_frame_rate, '/');
202+
web_stream.avg_frame_rate = gen_rational_str(stream->avg_frame_rate, '/');
203+
web_stream.rotation = get_rotation(stream);
204+
205+
AVRational sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
206+
if (sar.num) {
207+
AVRational dar;
208+
av_reduce(&dar.num, &dar.den, par->width * sar.num, par->height * sar.den, 1024 * 1024);
209+
web_stream.sample_aspect_ratio = gen_rational_str(sar, ':');
210+
web_stream.display_aspect_ratio = gen_rational_str(dar, ':');
211+
}
212+
164213
set_video_codec_string(codec_string, sizeof(codec_string), par, &stream->avg_frame_rate);
165214
}
166215
else if (par->codec_type == AVMEDIA_TYPE_AUDIO)
167216
{
217+
// Audio-specific properties
218+
web_stream.channels = par->ch_layout.nb_channels;
219+
web_stream.sample_rate = par->sample_rate;
220+
web_stream.sample_fmt = safe_str(av_get_sample_fmt_name((AVSampleFormat)par->format));
168221
set_audio_codec_string(codec_string, sizeof(codec_string), par);
169222
}
170223
else
171224
{
172225
strcpy(codec_string, "undf");
173226
}
174227

175-
web_stream.codec_string = codec_string;
176-
web_stream.profile = avcodec_profile_name(par->codec_id, par->profile);
177-
web_stream.pix_fmt = av_get_pix_fmt_name((AVPixelFormat)par->format);
228+
// Common properties for all types
229+
web_stream.codec_string = safe_str(codec_string);
230+
web_stream.profile = safe_str(avcodec_profile_name(par->codec_id, par->profile));
178231
web_stream.level = par->level;
179-
web_stream.width = par->width;
180-
web_stream.height = par->height;
181-
web_stream.channels = par->ch_layout.nb_channels;
182-
web_stream.sample_rate = par->sample_rate;
183-
web_stream.sample_fmt = av_get_sample_fmt_name((AVSampleFormat)par->format);
184232
web_stream.bit_rate = std::to_string(par->bit_rate);
233+
185234
web_stream.extradata_size = par->extradata_size;
186235
if (par->extradata_size > 0)
187236
{
@@ -192,10 +241,8 @@ void gen_web_stream(WebAVStream &web_stream, AVStream *stream, AVFormatContext *
192241
web_stream.extradata = std::vector<uint8_t>();
193242
}
194243

195-
// other stream info
196244
web_stream.start_time = stream->start_time * av_q2d(stream->time_base);
197245
web_stream.duration = stream->duration > 0 ? stream->duration * av_q2d(stream->time_base) : fmt_ctx->duration * av_q2d(AV_TIME_BASE_Q); // TODO: some file type can not get stream duration
198-
web_stream.rotation = get_rotation(stream);
199246

200247
int64_t nb_frames = stream->nb_frames;
201248

@@ -205,30 +252,13 @@ void gen_web_stream(WebAVStream &web_stream, AVStream *stream, AVFormatContext *
205252
nb_frames = (fmt_ctx->duration * (double)stream->avg_frame_rate.num) / ((double)stream->avg_frame_rate.den * AV_TIME_BASE);
206253
}
207254
web_stream.nb_frames = std::to_string(nb_frames);
208-
web_stream.r_frame_rate = gen_rational_str(stream->r_frame_rate, '/');
209-
web_stream.avg_frame_rate = gen_rational_str(stream->avg_frame_rate, '/');
210-
AVRational sar, dar;
211-
sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
212-
213-
if (sar.num)
214-
{
215-
av_reduce(&dar.num, &dar.den, par->width * sar.num, par->height * sar.den, 1024 * 1024);
216-
web_stream.sample_aspect_ratio = gen_rational_str(sar, ':');
217-
web_stream.display_aspect_ratio = gen_rational_str(dar, ':');
218-
}
219-
else
220-
{
221-
web_stream.sample_aspect_ratio = std::string("N/A");
222-
web_stream.display_aspect_ratio = std::string("N/A");
223-
}
224255

225256
AVDictionaryEntry *tag = NULL;
226-
227257
while ((tag = av_dict_get(stream->metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
228258
{
229259
Tag t = {
230-
.key = tag->key,
231-
.value = tag->value,
260+
.key = safe_str(tag->key),
261+
.value = safe_str(tag->value)
232262
};
233263
web_stream.tags.push_back(t);
234264
}
@@ -641,7 +671,7 @@ EMSCRIPTEN_BINDINGS(web_demuxer)
641671
.property("duration", &WebAVStream::duration)
642672
.property("rotation", &WebAVStream::rotation)
643673
.property("nb_frames", &WebAVStream::nb_frames)
644-
.property("tags", &WebAVStream::tags)
674+
.property("tags", &WebAVStream::get_tags)
645675
.property("color_primaries", &WebAVStream::color_primaries)
646676
.property("color_transfer", &WebAVStream::color_transfer)
647677
.property("color_space", &WebAVStream::color_space)

0 commit comments

Comments
 (0)