fftools/ffmpeg: replace OutputStream.file_index by a pointer

Reduces the need to use the output_files global array.
release/7.0
Anton Khirnov 11 months ago
parent 0fcea80b2a
commit 4224895a87
  1. 12
      fftools/ffmpeg.c
  2. 4
      fftools/ffmpeg.h
  3. 21
      fftools/ffmpeg_enc.c
  4. 22
      fftools/ffmpeg_filter.c
  5. 11
      fftools/ffmpeg_mux.c
  6. 12
      fftools/ffmpeg_mux_init.c

@ -374,7 +374,7 @@ static void ffmpeg_cleanup(int ret)
OutputStream *ost_iter(OutputStream *prev) OutputStream *ost_iter(OutputStream *prev)
{ {
int of_idx = prev ? prev->file_index : 0; int of_idx = prev ? prev->file->index : 0;
int ost_idx = prev ? prev->index + 1 : 0; int ost_idx = prev ? prev->index + 1 : 0;
for (; of_idx < nb_output_files; of_idx++) { for (; of_idx < nb_output_files; of_idx++) {
@ -530,7 +530,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
if (vid && ost->type == AVMEDIA_TYPE_VIDEO) { if (vid && ost->type == AVMEDIA_TYPE_VIDEO) {
av_bprintf(&buf, "q=%2.1f ", q); av_bprintf(&buf, "q=%2.1f ", q);
av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
ost->file_index, ost->index, q); ost->file->index, ost->index, q);
} }
if (!vid && ost->type == AVMEDIA_TYPE_VIDEO && ost->filter) { if (!vid && ost->type == AVMEDIA_TYPE_VIDEO && ost->filter) {
float fps; float fps;
@ -542,7 +542,7 @@ static void print_report(int is_last_report, int64_t timer_start, int64_t cur_ti
av_bprintf(&buf_script, "frame=%"PRId64"\n", frame_number); av_bprintf(&buf_script, "frame=%"PRId64"\n", frame_number);
av_bprintf(&buf_script, "fps=%.2f\n", fps); av_bprintf(&buf_script, "fps=%.2f\n", fps);
av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n", av_bprintf(&buf_script, "stream_%d_%d_q=%.1f\n",
ost->file_index, ost->index, q); ost->file->index, ost->index, q);
if (is_last_report) if (is_last_report)
av_bprintf(&buf, "L"); av_bprintf(&buf, "L");
@ -780,7 +780,7 @@ static void print_stream_maps(void)
if (ost->attachment_filename) { if (ost->attachment_filename) {
/* an attached file */ /* an attached file */
av_log(NULL, AV_LOG_INFO, " File %s -> Stream #%d:%d\n", av_log(NULL, AV_LOG_INFO, " File %s -> Stream #%d:%d\n",
ost->attachment_filename, ost->file_index, ost->index); ost->attachment_filename, ost->file->index, ost->index);
continue; continue;
} }
@ -790,7 +790,7 @@ static void print_stream_maps(void)
if (nb_filtergraphs > 1) if (nb_filtergraphs > 1)
av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index); av_log(NULL, AV_LOG_INFO, " (graph %d)", ost->filter->graph->index);
av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file_index, av_log(NULL, AV_LOG_INFO, " -> Stream #%d:%d (%s)\n", ost->file->index,
ost->index, ost->enc_ctx->codec->name); ost->index, ost->enc_ctx->codec->name);
continue; continue;
} }
@ -798,7 +798,7 @@ static void print_stream_maps(void)
av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d", av_log(NULL, AV_LOG_INFO, " Stream #%d:%d -> #%d:%d",
ost->ist->file->index, ost->ist->file->index,
ost->ist->index, ost->ist->index,
ost->file_index, ost->file->index,
ost->index); ost->index);
if (ost->enc_ctx) { if (ost->enc_ctx) {
const AVCodec *in_codec = ost->ist->dec; const AVCodec *in_codec = ost->ist->dec;

@ -519,7 +519,9 @@ typedef struct OutputStream {
enum AVMediaType type; enum AVMediaType type;
int file_index; /* file index */ /* parent muxer */
struct OutputFile *file;
int index; /* stream index in the output file */ int index; /* stream index in the output file */
/** /**

@ -173,7 +173,7 @@ int enc_open(void *opaque, const AVFrame *frame)
AVCodecContext *enc_ctx = ost->enc_ctx; AVCodecContext *enc_ctx = ost->enc_ctx;
AVCodecContext *dec_ctx = NULL; AVCodecContext *dec_ctx = NULL;
const AVCodec *enc = enc_ctx->codec; const AVCodec *enc = enc_ctx->codec;
OutputFile *of = output_files[ost->file_index]; OutputFile *of = ost->file;
FrameData *fd; FrameData *fd;
int frame_samples = 0; int frame_samples = 0;
int ret; int ret;
@ -189,7 +189,7 @@ int enc_open(void *opaque, const AVFrame *frame)
fd = (FrameData*)frame->opaque_ref->data; fd = (FrameData*)frame->opaque_ref->data;
} }
ret = set_encoder_id(output_files[ost->file_index], ost); ret = set_encoder_id(of, ost);
if (ret < 0) if (ret < 0)
return ret; return ret;
@ -375,7 +375,7 @@ int enc_open(void *opaque, const AVFrame *frame)
static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb) static int check_recording_time(OutputStream *ost, int64_t ts, AVRational tb)
{ {
OutputFile *of = output_files[ost->file_index]; OutputFile *of = ost->file;
if (of->recording_time != INT64_MAX && if (of->recording_time != INT64_MAX &&
av_compare_ts(ts, tb, of->recording_time, AV_TIME_BASE_Q) >= 0) { av_compare_ts(ts, tb, of->recording_time, AV_TIME_BASE_Q) >= 0) {
@ -414,8 +414,8 @@ static int do_subtitle_out(OutputFile *of, OutputStream *ost, const AVSubtitle *
/* shift timestamp to honor -ss and make check_recording_time() work with -t */ /* shift timestamp to honor -ss and make check_recording_time() work with -t */
pts = sub->pts; pts = sub->pts;
if (output_files[ost->file_index]->start_time != AV_NOPTS_VALUE) if (of->start_time != AV_NOPTS_VALUE)
pts -= output_files[ost->file_index]->start_time; pts -= of->start_time;
for (i = 0; i < nb; i++) { for (i = 0; i < nb; i++) {
AVSubtitle local_sub = *sub; AVSubtitle local_sub = *sub;
@ -496,7 +496,7 @@ void enc_stats_write(OutputStream *ost, EncStats *es,
switch (c->type) { switch (c->type) {
case ENC_STATS_LITERAL: avio_write (io, c->str, c->str_len); continue; case ENC_STATS_LITERAL: avio_write (io, c->str, c->str_len); continue;
case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file_index); continue; case ENC_STATS_FILE_IDX: avio_printf(io, "%d", ost->file->index); continue;
case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue; case ENC_STATS_STREAM_IDX: avio_printf(io, "%d", ost->index); continue;
case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue; case ENC_STATS_TIMEBASE: avio_printf(io, "%d/%d", tb.num, tb.den); continue;
case ENC_STATS_TIMEBASE_IN: avio_printf(io, "%d/%d", tbi.num, tbi.den); continue; case ENC_STATS_TIMEBASE_IN: avio_printf(io, "%d/%d", tbi.num, tbi.den); continue;
@ -584,7 +584,8 @@ static int update_video_stats(OutputStream *ost, const AVPacket *pkt, int write_
fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number, fprintf(vstats_file, "frame= %5"PRId64" q= %2.1f ", frame_number,
quality / (float)FF_QP2LAMBDA); quality / (float)FF_QP2LAMBDA);
} else { } else {
fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ", ost->file_index, ost->index, frame_number, fprintf(vstats_file, "out= %2d st= %2d frame= %5"PRId64" q= %2.1f ",
ost->file->index, ost->index, frame_number,
quality / (float)FF_QP2LAMBDA); quality / (float)FF_QP2LAMBDA);
} }
@ -659,7 +660,7 @@ static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame,
ret = avcodec_receive_packet(enc, pkt); ret = avcodec_receive_packet(enc, pkt);
update_benchmark("%s_%s %d.%d", action, type_desc, update_benchmark("%s_%s %d.%d", action, type_desc,
ost->file_index, ost->index); of->index, ost->index);
pkt->time_base = enc->time_base; pkt->time_base = enc->time_base;
@ -803,7 +804,7 @@ static int do_video_out(OutputFile *of, OutputStream *ost,
static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt) static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
{ {
OutputFile *of = output_files[ost->file_index]; OutputFile *of = ost->file;
enum AVMediaType type = ost->type; enum AVMediaType type = ost->type;
if (type == AVMEDIA_TYPE_SUBTITLE) { if (type == AVMEDIA_TYPE_SUBTITLE) {
@ -826,7 +827,7 @@ static int frame_encode(OutputStream *ost, AVFrame *frame, AVPacket *pkt)
static void enc_thread_set_name(const OutputStream *ost) static void enc_thread_set_name(const OutputStream *ost)
{ {
char name[16]; char name[16];
snprintf(name, sizeof(name), "enc%d:%d:%s", ost->file_index, ost->index, snprintf(name, sizeof(name), "enc%d:%d:%s", ost->file->index, ost->index,
ost->enc_ctx->codec->name); ost->enc_ctx->codec->name);
ff_thread_setname(name); ff_thread_setname(name);
} }

@ -721,7 +721,7 @@ static int set_channel_layout(OutputFilterPriv *f, OutputStream *ost)
int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost,
unsigned sched_idx_enc) unsigned sched_idx_enc)
{ {
const OutputFile *of = output_files[ost->file_index]; const OutputFile *of = ost->file;
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
FilterGraph *fg = ofilter->graph; FilterGraph *fg = ofilter->graph;
FilterGraphPriv *fgp = fgp_from_fg(fg); FilterGraphPriv *fgp = fgp_from_fg(fg);
@ -1041,7 +1041,7 @@ int init_simple_filtergraph(InputStream *ist, OutputStream *ost,
snprintf(fgp->log_name, sizeof(fgp->log_name), "%cf#%d:%d", snprintf(fgp->log_name, sizeof(fgp->log_name), "%cf#%d:%d",
av_get_media_type_string(ost->type)[0], av_get_media_type_string(ost->type)[0],
ost->file_index, ost->index); ost->file->index, ost->index);
if (fg->nb_inputs != 1 || fg->nb_outputs != 1) { if (fg->nb_inputs != 1 || fg->nb_outputs != 1) {
av_log(fg, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " av_log(fg, AV_LOG_ERROR, "Simple filtergraph '%s' was expected "
@ -1220,7 +1220,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
{ {
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
OutputStream *ost = ofilter->ost; OutputStream *ost = ofilter->ost;
OutputFile *of = output_files[ost->file_index]; OutputFile *of = ost->file;
AVFilterContext *last_filter = out->filter_ctx; AVFilterContext *last_filter = out->filter_ctx;
AVBPrint bprint; AVBPrint bprint;
int pad_idx = out->pad_idx; int pad_idx = out->pad_idx;
@ -1228,7 +1228,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
const char *pix_fmts; const char *pix_fmts;
char name[255]; char name[255];
snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); snprintf(name, sizeof(name), "out_%d_%d", ost->file->index, ost->index);
ret = avfilter_graph_create_filter(&ofp->filter, ret = avfilter_graph_create_filter(&ofp->filter,
avfilter_get_by_name("buffersink"), avfilter_get_by_name("buffersink"),
name, NULL, NULL, graph); name, NULL, NULL, graph);
@ -1249,7 +1249,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
} }
snprintf(name, sizeof(name), "scaler_out_%d_%d", snprintf(name, sizeof(name), "scaler_out_%d_%d",
ost->file_index, ost->index); ost->file->index, ost->index);
if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
name, args, NULL, graph)) < 0) name, args, NULL, graph)) < 0)
return ret; return ret;
@ -1282,7 +1282,7 @@ static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph,
} }
snprintf(name, sizeof(name), "trim_out_%d_%d", snprintf(name, sizeof(name), "trim_out_%d_%d",
ost->file_index, ost->index); ost->file->index, ost->index);
ret = insert_trim(of->start_time, of->recording_time, ret = insert_trim(of->start_time, of->recording_time,
&last_filter, &pad_idx, name); &last_filter, &pad_idx, name);
if (ret < 0) if (ret < 0)
@ -1300,14 +1300,14 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
{ {
OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); OutputFilterPriv *ofp = ofp_from_ofilter(ofilter);
OutputStream *ost = ofilter->ost; OutputStream *ost = ofilter->ost;
OutputFile *of = output_files[ost->file_index]; OutputFile *of = ost->file;
AVFilterContext *last_filter = out->filter_ctx; AVFilterContext *last_filter = out->filter_ctx;
int pad_idx = out->pad_idx; int pad_idx = out->pad_idx;
AVBPrint args; AVBPrint args;
char name[255]; char name[255];
int ret; int ret;
snprintf(name, sizeof(name), "out_%d_%d", ost->file_index, ost->index); snprintf(name, sizeof(name), "out_%d_%d", ost->file->index, ost->index);
ret = avfilter_graph_create_filter(&ofp->filter, ret = avfilter_graph_create_filter(&ofp->filter,
avfilter_get_by_name("abuffersink"), avfilter_get_by_name("abuffersink"),
name, NULL, NULL, graph); name, NULL, NULL, graph);
@ -1362,7 +1362,7 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
AVFilterContext *format; AVFilterContext *format;
snprintf(name, sizeof(name), "format_out_%d_%d", snprintf(name, sizeof(name), "format_out_%d_%d",
ost->file_index, ost->index); ost->file->index, ost->index);
ret = avfilter_graph_create_filter(&format, ret = avfilter_graph_create_filter(&format,
avfilter_get_by_name("aformat"), avfilter_get_by_name("aformat"),
name, args.str, NULL, graph); name, args.str, NULL, graph);
@ -1390,7 +1390,7 @@ static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph,
} }
snprintf(name, sizeof(name), "trim for output stream %d:%d", snprintf(name, sizeof(name), "trim for output stream %d:%d",
ost->file_index, ost->index); ost->file->index, ost->index);
ret = insert_trim(of->start_time, of->recording_time, ret = insert_trim(of->start_time, of->recording_time,
&last_filter, &pad_idx, name); &last_filter, &pad_idx, name);
if (ret < 0) if (ret < 0)
@ -2684,7 +2684,7 @@ static void fg_thread_set_name(const FilterGraph *fg)
OutputStream *ost = fg->outputs[0]->ost; OutputStream *ost = fg->outputs[0]->ost;
snprintf(name, sizeof(name), "%cf#%d:%d", snprintf(name, sizeof(name), "%cf#%d:%d",
av_get_media_type_string(ost->type)[0], av_get_media_type_string(ost->type)[0],
ost->file_index, ost->index); ost->file->index, ost->index);
} else { } else {
snprintf(name, sizeof(name), "fc%d", fg->index); snprintf(name, sizeof(name), "fc%d", fg->index);
} }

@ -178,7 +178,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
pkt->dts > pkt->pts) { pkt->dts > pkt->pts) {
av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n", av_log(s, AV_LOG_WARNING, "Invalid DTS: %"PRId64" PTS: %"PRId64" in output stream %d:%d, replacing by guess\n",
pkt->dts, pkt->pts, pkt->dts, pkt->pts,
ost->file_index, ost->st->index); mux->of.index, ost->st->index);
pkt->pts = pkt->pts =
pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1 pkt->dts = pkt->pts + pkt->dts + ms->last_mux_dts + 1
- FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1) - FFMIN3(pkt->pts, pkt->dts, ms->last_mux_dts + 1)
@ -194,7 +194,7 @@ static int write_packet(Muxer *mux, OutputStream *ost, AVPacket *pkt)
loglevel = AV_LOG_ERROR; loglevel = AV_LOG_ERROR;
av_log(s, loglevel, "Non-monotonic DTS in output stream " av_log(s, loglevel, "Non-monotonic DTS in output stream "
"%d:%d; previous: %"PRId64", current: %"PRId64"; ", "%d:%d; previous: %"PRId64", current: %"PRId64"; ",
ost->file_index, ost->st->index, ms->last_mux_dts, pkt->dts); mux->of.index, ost->st->index, ms->last_mux_dts, pkt->dts);
if (exit_on_error) { if (exit_on_error) {
ret = AVERROR(EINVAL); ret = AVERROR(EINVAL);
goto fail; goto fail;
@ -271,7 +271,7 @@ static int sync_queue_process(Muxer *mux, OutputStream *ost, AVPacket *pkt, int
return 0; return 0;
} }
static int of_streamcopy(OutputStream *ost, AVPacket *pkt); static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt);
/* apply the output bitstream filters */ /* apply the output bitstream filters */
static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt, static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt,
@ -282,7 +282,7 @@ static int mux_packet_filter(Muxer *mux, MuxThreadContext *mt,
int ret = 0; int ret = 0;
if (pkt && !ost->enc) { if (pkt && !ost->enc) {
ret = of_streamcopy(ost, pkt); ret = of_streamcopy(&mux->of, ost, pkt);
if (ret == AVERROR(EAGAIN)) if (ret == AVERROR(EAGAIN))
return 0; return 0;
else if (ret == AVERROR_EOF) { else if (ret == AVERROR_EOF) {
@ -445,9 +445,8 @@ finish:
return (void*)(intptr_t)ret; return (void*)(intptr_t)ret;
} }
static int of_streamcopy(OutputStream *ost, AVPacket *pkt) static int of_streamcopy(OutputFile *of, OutputStream *ost, AVPacket *pkt)
{ {
OutputFile *of = output_files[ost->file_index];
MuxStream *ms = ms_from_ost(ost); MuxStream *ms = ms_from_ost(ost);
FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL; FrameData *fd = pkt->opaque_ref ? (FrameData*)pkt->opaque_ref->data : NULL;
int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE; int64_t dts = fd ? fd->dts_est : AV_NOPTS_VALUE;

@ -431,7 +431,7 @@ static MuxStream *mux_stream_alloc(Muxer *mux, enum AVMediaType type)
if (!ms) if (!ms)
return NULL; return NULL;
ms->ost.file_index = mux->of.index; ms->ost.file = &mux->of;
ms->ost.index = mux->of.nb_streams - 1; ms->ost.index = mux->of.nb_streams - 1;
ms->ost.type = type; ms->ost.type = type;
@ -748,7 +748,7 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
FILE *f; FILE *f;
/* compute this stream's global index */ /* compute this stream's global index */
for (int i = 0; i <= ost->file_index; i++) for (int i = 0; i <= ost->file->index; i++)
ost_idx += output_files[i]->nb_streams; ost_idx += output_files[i]->nb_streams;
snprintf(logfilename, sizeof(logfilename), "%s-%d.log", snprintf(logfilename, sizeof(logfilename), "%s-%d.log",
@ -793,7 +793,7 @@ static int new_stream_video(Muxer *mux, const OptionsContext *o,
ost->vsync_method = video_sync_method; ost->vsync_method = video_sync_method;
MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st); MATCH_PER_STREAM_OPT(fps_mode, str, fps_mode, oc, st);
if (fps_mode) { if (fps_mode) {
ret = parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file_index, ost->index, 0); ret = parse_and_set_vsync(fps_mode, &ost->vsync_method, ost->file->index, ost->index, 0);
if (ret < 0) if (ret < 0)
return ret; return ret;
} }
@ -893,7 +893,7 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
/* check for channel mapping for this audio stream */ /* check for channel mapping for this audio stream */
for (int n = 0; n < o->nb_audio_channel_maps; n++) { for (int n = 0; n < o->nb_audio_channel_maps; n++) {
AudioChannelMap *map = &o->audio_channel_maps[n]; AudioChannelMap *map = &o->audio_channel_maps[n];
if ((map->ofile_idx == -1 || ost->file_index == map->ofile_idx) && if ((map->ofile_idx == -1 || ost->file->index == map->ofile_idx) &&
(map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) { (map->ostream_idx == -1 || ost->st->index == map->ostream_idx)) {
InputStream *ist; InputStream *ist;
@ -901,7 +901,7 @@ static int new_stream_audio(Muxer *mux, const OptionsContext *o,
ist = NULL; ist = NULL;
} else if (!ost->ist) { } else if (!ost->ist) {
av_log(ost, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n", av_log(ost, AV_LOG_FATAL, "Cannot determine input stream for channel mapping %d.%d\n",
ost->file_index, ost->st->index); ost->file->index, ost->st->index);
continue; continue;
} else { } else {
ist = ost->ist; ist = ost->ist;
@ -1481,7 +1481,7 @@ static int ost_add(Muxer *mux, const OptionsContext *o, enum AVMediaType type,
return ret; return ret;
} else { } else {
ret = sch_connect(mux->sch, SCH_DSTREAM(ost->ist->file->index, sched_idx), ret = sch_connect(mux->sch, SCH_DSTREAM(ost->ist->file->index, sched_idx),
SCH_MSTREAM(ost->file_index, ms->sch_idx)); SCH_MSTREAM(ost->file->index, ms->sch_idx));
if (ret < 0) if (ret < 0)
return ret; return ret;
} }

Loading…
Cancel
Save