diff --git a/doc/examples/decode_audio.c b/doc/examples/decode_audio.c index 6c2a8ed550..49ad22cba6 100644 --- a/doc/examples/decode_audio.c +++ b/doc/examples/decode_audio.c @@ -97,7 +97,7 @@ static void decode(AVCodecContext *dec_ctx, AVPacket *pkt, AVFrame *frame, exit(1); } for (i = 0; i < frame->nb_samples; i++) - for (ch = 0; ch < dec_ctx->channels; ch++) + for (ch = 0; ch < dec_ctx->ch_layout.nb_channels; ch++) fwrite(frame->data[ch] + data_size*i, 1, data_size, outfile); } } @@ -215,7 +215,7 @@ int main(int argc, char **argv) sfmt = av_get_packed_sample_fmt(sfmt); } - n_channels = c->channels; + n_channels = c->ch_layout.nb_channels; if ((ret = get_format_from_sample_fmt(&fmt, sfmt)) < 0) goto end; diff --git a/doc/examples/demuxing_decoding.c b/doc/examples/demuxing_decoding.c index 8520d5b660..999a78db0d 100644 --- a/doc/examples/demuxing_decoding.c +++ b/doc/examples/demuxing_decoding.c @@ -345,7 +345,7 @@ int main (int argc, char **argv) if (audio_stream) { enum AVSampleFormat sfmt = audio_dec_ctx->sample_fmt; - int n_channels = audio_dec_ctx->channels; + int n_channels = audio_dec_ctx->ch_layout.nb_channels; const char *fmt; if (av_sample_fmt_is_planar(sfmt)) { diff --git a/doc/examples/encode_audio.c b/doc/examples/encode_audio.c index ab3586be7f..9a1792b725 100644 --- a/doc/examples/encode_audio.c +++ b/doc/examples/encode_audio.c @@ -70,26 +70,25 @@ static int select_sample_rate(const AVCodec *codec) } /* select layout with the highest channel count */ -static int select_channel_layout(const AVCodec *codec) +static int select_channel_layout(const AVCodec *codec, AVChannelLayout *dst) { - const uint64_t *p; - uint64_t best_ch_layout = 0; + const AVChannelLayout *p, *best_ch_layout; int best_nb_channels = 0; - if (!codec->channel_layouts) - return AV_CH_LAYOUT_STEREO; + if (!codec->ch_layouts) + return av_channel_layout_copy(dst, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); - p = codec->channel_layouts; - while (*p) { - int nb_channels = av_get_channel_layout_nb_channels(*p); + p = codec->ch_layouts; + while (p->nb_channels) { + int nb_channels = p->nb_channels; if (nb_channels > best_nb_channels) { - best_ch_layout = *p; + best_ch_layout = p; best_nb_channels = nb_channels; } p++; } - return best_ch_layout; + return av_channel_layout_copy(dst, best_ch_layout); } static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, @@ -164,8 +163,9 @@ int main(int argc, char **argv) /* select other audio parameters supported by the encoder */ c->sample_rate = select_sample_rate(codec); - c->channel_layout = select_channel_layout(codec); - c->channels = av_get_channel_layout_nb_channels(c->channel_layout); + ret = select_channel_layout(codec, &c->ch_layout); + if (ret < 0) + exit(1); /* open it */ if (avcodec_open2(c, codec, NULL) < 0) { @@ -195,7 +195,9 @@ int main(int argc, char **argv) frame->nb_samples = c->frame_size; frame->format = c->sample_fmt; - frame->channel_layout = c->channel_layout; + ret = av_channel_layout_copy(&frame->ch_layout, &c->ch_layout); + if (ret < 0) + exit(1); /* allocate the data buffers */ ret = av_frame_get_buffer(frame, 0); @@ -218,7 +220,7 @@ int main(int argc, char **argv) for (j = 0; j < c->frame_size; j++) { samples[2*j] = (int)(sin(t) * 10000); - for (k = 1; k < c->channels; k++) + for (k = 1; k < c->ch_layout.nb_channels; k++) samples[2*j + k] = samples[2*j]; t += tincr; } diff --git a/doc/examples/filter_audio.c b/doc/examples/filter_audio.c index 1611e3d952..f53e52562b 100644 --- a/doc/examples/filter_audio.c +++ b/doc/examples/filter_audio.c @@ -55,7 +55,7 @@ #define INPUT_SAMPLERATE 48000 #define INPUT_FORMAT AV_SAMPLE_FMT_FLTP -#define INPUT_CHANNEL_LAYOUT AV_CH_LAYOUT_5POINT0 +#define INPUT_CHANNEL_LAYOUT (AVChannelLayout)AV_CHANNEL_LAYOUT_5POINT0 #define VOLUME_VAL 0.90 @@ -100,7 +100,7 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src, } /* Set the filter options through the AVOptions API. */ - av_get_channel_layout_string(ch_layout, sizeof(ch_layout), 0, INPUT_CHANNEL_LAYOUT); + av_channel_layout_describe(&INPUT_CHANNEL_LAYOUT, ch_layout, sizeof(ch_layout)); av_opt_set (abuffer_ctx, "channel_layout", ch_layout, AV_OPT_SEARCH_CHILDREN); av_opt_set (abuffer_ctx, "sample_fmt", av_get_sample_fmt_name(INPUT_FORMAT), AV_OPT_SEARCH_CHILDREN); av_opt_set_q (abuffer_ctx, "time_base", (AVRational){ 1, INPUT_SAMPLERATE }, AV_OPT_SEARCH_CHILDREN); @@ -154,9 +154,8 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src, /* A third way of passing the options is in a string of the form * key1=value1:key2=value2.... */ snprintf(options_str, sizeof(options_str), - "sample_fmts=%s:sample_rates=%d:channel_layouts=0x%"PRIx64, - av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 44100, - (uint64_t)AV_CH_LAYOUT_STEREO); + "sample_fmts=%s:sample_rates=%d:channel_layouts=stereo", + av_get_sample_fmt_name(AV_SAMPLE_FMT_S16), 44100); err = avfilter_init_str(aformat_ctx, options_str); if (err < 0) { av_log(NULL, AV_LOG_ERROR, "Could not initialize the aformat filter.\n"); @@ -215,7 +214,7 @@ static int init_filter_graph(AVFilterGraph **graph, AVFilterContext **src, static int process_output(struct AVMD5 *md5, AVFrame *frame) { int planar = av_sample_fmt_is_planar(frame->format); - int channels = av_get_channel_layout_nb_channels(frame->channel_layout); + int channels = frame->ch_layout.nb_channels; int planes = planar ? channels : 1; int bps = av_get_bytes_per_sample(frame->format); int plane_size = bps * frame->nb_samples * (planar ? 1 : channels); @@ -248,7 +247,7 @@ static int get_input(AVFrame *frame, int frame_num) /* Set up the frame properties and allocate the buffer for the data. */ frame->sample_rate = INPUT_SAMPLERATE; frame->format = INPUT_FORMAT; - frame->channel_layout = INPUT_CHANNEL_LAYOUT; + av_channel_layout_copy(&frame->ch_layout, &INPUT_CHANNEL_LAYOUT); frame->nb_samples = FRAME_SIZE; frame->pts = frame_num * FRAME_SIZE; diff --git a/doc/examples/filtering_audio.c b/doc/examples/filtering_audio.c index 7d0eb19bbe..51fc47be2a 100644 --- a/doc/examples/filtering_audio.c +++ b/doc/examples/filtering_audio.c @@ -94,7 +94,6 @@ static int init_filters(const char *filters_descr) AVFilterInOut *outputs = avfilter_inout_alloc(); AVFilterInOut *inputs = avfilter_inout_alloc(); static const enum AVSampleFormat out_sample_fmts[] = { AV_SAMPLE_FMT_S16, -1 }; - static const int64_t out_channel_layouts[] = { AV_CH_LAYOUT_MONO, -1 }; static const int out_sample_rates[] = { 8000, -1 }; const AVFilterLink *outlink; AVRational time_base = fmt_ctx->streams[audio_stream_index]->time_base; @@ -106,12 +105,13 @@ static int init_filters(const char *filters_descr) } /* buffer audio source: the decoded frames from the decoder will be inserted here. */ - if (!dec_ctx->channel_layout) - dec_ctx->channel_layout = av_get_default_channel_layout(dec_ctx->channels); - snprintf(args, sizeof(args), - "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, + if (dec_ctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&dec_ctx->ch_layout, dec_ctx->ch_layout.nb_channels); + ret = snprintf(args, sizeof(args), + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=", time_base.num, time_base.den, dec_ctx->sample_rate, - av_get_sample_fmt_name(dec_ctx->sample_fmt), dec_ctx->channel_layout); + av_get_sample_fmt_name(dec_ctx->sample_fmt)); + av_channel_layout_describe(&dec_ctx->ch_layout, args + ret, sizeof(args) - ret); ret = avfilter_graph_create_filter(&buffersrc_ctx, abuffersrc, "in", args, NULL, filter_graph); if (ret < 0) { @@ -134,7 +134,7 @@ static int init_filters(const char *filters_descr) goto end; } - ret = av_opt_set_int_list(buffersink_ctx, "channel_layouts", out_channel_layouts, -1, + ret = av_opt_set(buffersink_ctx, "ch_layouts", "mono", AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n"); @@ -185,7 +185,7 @@ static int init_filters(const char *filters_descr) /* Print summary of the sink buffer * Note: args buffer is reused to store channel layout string */ outlink = buffersink_ctx->inputs[0]; - av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout); + av_channel_layout_describe(&outlink->ch_layout, args, sizeof(args)); av_log(NULL, AV_LOG_INFO, "Output: srate:%dHz fmt:%s chlayout:%s\n", (int)outlink->sample_rate, (char *)av_x_if_null(av_get_sample_fmt_name(outlink->format), "?"), @@ -200,7 +200,7 @@ end: static void print_frame(const AVFrame *frame) { - const int n = frame->nb_samples * av_get_channel_layout_nb_channels(frame->channel_layout); + const int n = frame->nb_samples * frame->ch_layout.nb_channels; const uint16_t *p = (uint16_t*)frame->data[0]; const uint16_t *p_end = p + n; diff --git a/doc/examples/muxing.c b/doc/examples/muxing.c index 8a11e52842..aea3197b4d 100644 --- a/doc/examples/muxing.c +++ b/doc/examples/muxing.c @@ -170,16 +170,7 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc, c->sample_rate = 44100; } } - c->channels = av_get_channel_layout_nb_channels(c->channel_layout); - c->channel_layout = AV_CH_LAYOUT_STEREO; - if ((*codec)->channel_layouts) { - c->channel_layout = (*codec)->channel_layouts[0]; - for (i = 0; (*codec)->channel_layouts[i]; i++) { - if ((*codec)->channel_layouts[i] == AV_CH_LAYOUT_STEREO) - c->channel_layout = AV_CH_LAYOUT_STEREO; - } - } - c->channels = av_get_channel_layout_nb_channels(c->channel_layout); + av_channel_layout_copy(&c->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); ost->st->time_base = (AVRational){ 1, c->sample_rate }; break; @@ -224,7 +215,7 @@ static void add_stream(OutputStream *ost, AVFormatContext *oc, /* audio output */ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt, - uint64_t channel_layout, + const AVChannelLayout *channel_layout, int sample_rate, int nb_samples) { AVFrame *frame = av_frame_alloc(); @@ -236,7 +227,7 @@ static AVFrame *alloc_audio_frame(enum AVSampleFormat sample_fmt, } frame->format = sample_fmt; - frame->channel_layout = channel_layout; + av_channel_layout_copy(&frame->ch_layout, channel_layout); frame->sample_rate = sample_rate; frame->nb_samples = nb_samples; @@ -281,9 +272,9 @@ static void open_audio(AVFormatContext *oc, const AVCodec *codec, else nb_samples = c->frame_size; - ost->frame = alloc_audio_frame(c->sample_fmt, c->channel_layout, + ost->frame = alloc_audio_frame(c->sample_fmt, &c->ch_layout, c->sample_rate, nb_samples); - ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, c->channel_layout, + ost->tmp_frame = alloc_audio_frame(AV_SAMPLE_FMT_S16, &c->ch_layout, c->sample_rate, nb_samples); /* copy the stream parameters to the muxer */ @@ -301,10 +292,10 @@ static void open_audio(AVFormatContext *oc, const AVCodec *codec, } /* set options */ - av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0); + av_opt_set_chlayout (ost->swr_ctx, "in_chlayout", &c->ch_layout, 0); av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0); - av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0); + av_opt_set_chlayout (ost->swr_ctx, "out_chlayout", &c->ch_layout, 0); av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0); av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0); @@ -330,7 +321,7 @@ static AVFrame *get_audio_frame(OutputStream *ost) for (j = 0; j nb_samples; j++) { v = (int)(sin(ost->t) * 10000); - for (i = 0; i < ost->enc->channels; i++) + for (i = 0; i < ost->enc->ch_layout.nb_channels; i++) *q++ = v; ost->t += ost->tincr; ost->tincr += ost->tincr2; diff --git a/doc/examples/resampling_audio.c b/doc/examples/resampling_audio.c index f35e7e1779..9f1521a5a5 100644 --- a/doc/examples/resampling_audio.c +++ b/doc/examples/resampling_audio.c @@ -80,7 +80,7 @@ static void fill_samples(double *dst, int nb_samples, int nb_channels, int sampl int main(int argc, char **argv) { - int64_t src_ch_layout = AV_CH_LAYOUT_STEREO, dst_ch_layout = AV_CH_LAYOUT_SURROUND; + AVChannelLayout src_ch_layout = AV_CHANNEL_LAYOUT_STEREO, dst_ch_layout = AV_CHANNEL_LAYOUT_SURROUND; int src_rate = 48000, dst_rate = 44100; uint8_t **src_data = NULL, **dst_data = NULL; int src_nb_channels = 0, dst_nb_channels = 0; @@ -92,6 +92,7 @@ int main(int argc, char **argv) int dst_bufsize; const char *fmt; struct SwrContext *swr_ctx; + char buf[64]; double t; int ret; @@ -120,11 +121,11 @@ int main(int argc, char **argv) } /* set options */ - av_opt_set_int(swr_ctx, "in_channel_layout", src_ch_layout, 0); + av_opt_set_chlayout(swr_ctx, "in_chlayout", &src_ch_layout, 0); av_opt_set_int(swr_ctx, "in_sample_rate", src_rate, 0); av_opt_set_sample_fmt(swr_ctx, "in_sample_fmt", src_sample_fmt, 0); - av_opt_set_int(swr_ctx, "out_channel_layout", dst_ch_layout, 0); + av_opt_set_chlayout(swr_ctx, "out_chlayout", &dst_ch_layout, 0); av_opt_set_int(swr_ctx, "out_sample_rate", dst_rate, 0); av_opt_set_sample_fmt(swr_ctx, "out_sample_fmt", dst_sample_fmt, 0); @@ -136,7 +137,7 @@ int main(int argc, char **argv) /* allocate source and destination samples buffers */ - src_nb_channels = av_get_channel_layout_nb_channels(src_ch_layout); + src_nb_channels = src_ch_layout.nb_channels; ret = av_samples_alloc_array_and_samples(&src_data, &src_linesize, src_nb_channels, src_nb_samples, src_sample_fmt, 0); if (ret < 0) { @@ -151,7 +152,7 @@ int main(int argc, char **argv) av_rescale_rnd(src_nb_samples, dst_rate, src_rate, AV_ROUND_UP); /* buffer is going to be directly written to a rawaudio file, no alignment */ - dst_nb_channels = av_get_channel_layout_nb_channels(dst_ch_layout); + dst_nb_channels = dst_ch_layout.nb_channels; ret = av_samples_alloc_array_and_samples(&dst_data, &dst_linesize, dst_nb_channels, dst_nb_samples, dst_sample_fmt, 0); if (ret < 0) { @@ -194,9 +195,10 @@ int main(int argc, char **argv) if ((ret = get_format_from_sample_fmt(&fmt, dst_sample_fmt)) < 0) goto end; + av_channel_layout_describe(&dst_ch_layout, buf, sizeof(buf)); fprintf(stderr, "Resampling succeeded. Play the output file with the command:\n" - "ffplay -f %s -channel_layout %"PRId64" -channels %d -ar %d %s\n", - fmt, dst_ch_layout, dst_nb_channels, dst_rate, dst_filename); + "ffplay -f %s -channel_layout %s -channels %d -ar %d %s\n", + fmt, buf, dst_nb_channels, dst_rate, dst_filename); end: fclose(dst_file); diff --git a/doc/examples/transcode_aac.c b/doc/examples/transcode_aac.c index 1cf6317e27..9102e55f16 100644 --- a/doc/examples/transcode_aac.c +++ b/doc/examples/transcode_aac.c @@ -200,8 +200,7 @@ static int open_output_file(const char *filename, /* Set the basic encoder parameters. * The input file's sample rate is used to avoid a sample rate conversion. */ - avctx->channels = OUTPUT_CHANNELS; - avctx->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS); + av_channel_layout_default(&avctx->ch_layout, OUTPUT_CHANNELS); avctx->sample_rate = input_codec_context->sample_rate; avctx->sample_fmt = output_codec->sample_fmts[0]; avctx->bit_rate = OUTPUT_BIT_RATE; @@ -290,21 +289,18 @@ static int init_resampler(AVCodecContext *input_codec_context, /* * Create a resampler context for the conversion. * Set the conversion parameters. - * Default channel layouts based on the number of channels - * are assumed for simplicity (they are sometimes not detected - * properly by the demuxer and/or decoder). */ - *resample_context = swr_alloc_set_opts(NULL, - av_get_default_channel_layout(output_codec_context->channels), + error = swr_alloc_set_opts2(resample_context, + &output_codec_context->ch_layout, output_codec_context->sample_fmt, output_codec_context->sample_rate, - av_get_default_channel_layout(input_codec_context->channels), + &input_codec_context->ch_layout, input_codec_context->sample_fmt, input_codec_context->sample_rate, 0, NULL); - if (!*resample_context) { + if (error < 0) { fprintf(stderr, "Could not allocate resample context\n"); - return AVERROR(ENOMEM); + return error; } /* * Perform a sanity check so that the number of converted samples is @@ -332,7 +328,7 @@ static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context) { /* Create the FIFO buffer based on the specified output sample format. */ if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt, - output_codec_context->channels, 1))) { + output_codec_context->ch_layout.nb_channels, 1))) { fprintf(stderr, "Could not allocate FIFO\n"); return AVERROR(ENOMEM); } @@ -450,7 +446,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples, * Each pointer will later point to the audio samples of the corresponding * channels (although it may be NULL for interleaved formats). */ - if (!(*converted_input_samples = calloc(output_codec_context->channels, + if (!(*converted_input_samples = calloc(output_codec_context->ch_layout.nb_channels, sizeof(**converted_input_samples)))) { fprintf(stderr, "Could not allocate converted input sample pointers\n"); return AVERROR(ENOMEM); @@ -459,7 +455,7 @@ static int init_converted_samples(uint8_t ***converted_input_samples, /* Allocate memory for the samples of all channels in one consecutive * block for convenience. */ if ((error = av_samples_alloc(*converted_input_samples, NULL, - output_codec_context->channels, + output_codec_context->ch_layout.nb_channels, frame_size, output_codec_context->sample_fmt, 0)) < 0) { fprintf(stderr, @@ -633,7 +629,7 @@ static int init_output_frame(AVFrame **frame, * Default channel layouts based on the number of channels * are assumed for simplicity. */ (*frame)->nb_samples = frame_size; - (*frame)->channel_layout = output_codec_context->channel_layout; + av_channel_layout_copy(&(*frame)->ch_layout, &output_codec_context->ch_layout); (*frame)->format = output_codec_context->sample_fmt; (*frame)->sample_rate = output_codec_context->sample_rate; diff --git a/doc/examples/transcoding.c b/doc/examples/transcoding.c index badfba62cb..013f89fc7d 100644 --- a/doc/examples/transcoding.c +++ b/doc/examples/transcoding.c @@ -175,8 +175,9 @@ static int open_output_file(const char *filename) enc_ctx->time_base = av_inv_q(dec_ctx->framerate); } else { enc_ctx->sample_rate = dec_ctx->sample_rate; - enc_ctx->channel_layout = dec_ctx->channel_layout; - enc_ctx->channels = av_get_channel_layout_nb_channels(enc_ctx->channel_layout); + ret = av_channel_layout_copy(&enc_ctx->ch_layout, &dec_ctx->ch_layout); + if (ret < 0) + return ret; /* take first format from list of supported formats */ enc_ctx->sample_fmt = encoder->sample_fmts[0]; enc_ctx->time_base = (AVRational){1, enc_ctx->sample_rate}; @@ -289,6 +290,7 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, goto end; } } else if (dec_ctx->codec_type == AVMEDIA_TYPE_AUDIO) { + char buf[64]; buffersrc = avfilter_get_by_name("abuffer"); buffersink = avfilter_get_by_name("abuffersink"); if (!buffersrc || !buffersink) { @@ -297,14 +299,14 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, goto end; } - if (!dec_ctx->channel_layout) - dec_ctx->channel_layout = - av_get_default_channel_layout(dec_ctx->channels); + if (dec_ctx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC) + av_channel_layout_default(&dec_ctx->ch_layout, dec_ctx->ch_layout.nb_channels); + av_channel_layout_describe(&dec_ctx->ch_layout, buf, sizeof(buf)); snprintf(args, sizeof(args), - "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, + "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s", dec_ctx->time_base.num, dec_ctx->time_base.den, dec_ctx->sample_rate, av_get_sample_fmt_name(dec_ctx->sample_fmt), - dec_ctx->channel_layout); + buf); ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in", args, NULL, filter_graph); if (ret < 0) { @@ -327,9 +329,9 @@ static int init_filter(FilteringContext* fctx, AVCodecContext *dec_ctx, goto end; } - ret = av_opt_set_bin(buffersink_ctx, "channel_layouts", - (uint8_t*)&enc_ctx->channel_layout, - sizeof(enc_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN); + av_channel_layout_describe(&enc_ctx->ch_layout, buf, sizeof(buf)); + ret = av_opt_set(buffersink_ctx, "ch_layouts", + buf, AV_OPT_SEARCH_CHILDREN); if (ret < 0) { av_log(NULL, AV_LOG_ERROR, "Cannot set output channel layout\n"); goto end;