void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)

{

    const char *codec_type;

    const char *codec_name;

    const char *profile = NULL;

    const AVCodec *p;

    int64_t bitrate;

    int new_line = 0;

    AVRational display_aspect_ratio;

    const char *separator = enc->dump_separator ? (const char *)enc->dump_separator : ", ";



    if (!buf || buf_size <= 0)

        return;

    codec_type = av_get_media_type_string(enc->codec_type);

    codec_name = avcodec_get_name(enc->codec_id);

    if (enc->profile != FF_PROFILE_UNKNOWN) {

        if (enc->codec)

            p = enc->codec;

        else

            p = encode ? avcodec_find_encoder(enc->codec_id) :

                        avcodec_find_decoder(enc->codec_id);

        if (p)

            profile = av_get_profile_name(p, enc->profile);

    }



    snprintf(buf, buf_size, "%s: %s", codec_type ? codec_type : "unknown",

             codec_name);

    buf[0] ^= 'a' ^ 'A'; /* first letter in uppercase */



    if (enc->codec && strcmp(enc->codec->name, codec_name))

        snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", enc->codec->name);



    if (profile)

        snprintf(buf + strlen(buf), buf_size - strlen(buf), " (%s)", profile);

    if (   enc->codec_type == AVMEDIA_TYPE_VIDEO

        && av_log_get_level() >= AV_LOG_VERBOSE

        && enc->refs)

        snprintf(buf + strlen(buf), buf_size - strlen(buf),

                 ", %d reference frame%s",

                 enc->refs, enc->refs > 1 ? "s" : "");



    if (enc->codec_tag) {

        char tag_buf[32];

        av_get_codec_tag_string(tag_buf, sizeof(tag_buf), enc->codec_tag);

        snprintf(buf + strlen(buf), buf_size - strlen(buf),

                 " (%s / 0x%04X)", tag_buf, enc->codec_tag);

    }



    switch (enc->codec_type) {

    case AVMEDIA_TYPE_VIDEO:

        {

            char detail[256] = "(";



            av_strlcat(buf, separator, buf_size);



            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                 "%s", enc->pix_fmt == AV_PIX_FMT_NONE ? "none" :

                     av_get_pix_fmt_name(enc->pix_fmt));

            if (enc->bits_per_raw_sample && enc->pix_fmt != AV_PIX_FMT_NONE &&

                enc->bits_per_raw_sample < av_pix_fmt_desc_get(enc->pix_fmt)->comp[0].depth)

                av_strlcatf(detail, sizeof(detail), "%d bpc, ", enc->bits_per_raw_sample);

            if (enc->color_range != AVCOL_RANGE_UNSPECIFIED)

                av_strlcatf(detail, sizeof(detail), "%s, ",

                            av_color_range_name(enc->color_range));



            if (enc->colorspace != AVCOL_SPC_UNSPECIFIED ||

                enc->color_primaries != AVCOL_PRI_UNSPECIFIED ||

                enc->color_trc != AVCOL_TRC_UNSPECIFIED) {

                if (enc->colorspace != (int)enc->color_primaries ||

                    enc->colorspace != (int)enc->color_trc) {

                    new_line = 1;

                    av_strlcatf(detail, sizeof(detail), "%s/%s/%s, ",

                                av_color_space_name(enc->colorspace),

                                av_color_primaries_name(enc->color_primaries),

                                av_color_transfer_name(enc->color_trc));

                } else

                    av_strlcatf(detail, sizeof(detail), "%s, ",

                                av_get_colorspace_name(enc->colorspace));

            }



            if (av_log_get_level() >= AV_LOG_DEBUG &&

                enc->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED)

                av_strlcatf(detail, sizeof(detail), "%s, ",

                            av_chroma_location_name(enc->chroma_sample_location));



            if (strlen(detail) > 1) {

                detail[strlen(detail) - 2] = 0;

                av_strlcatf(buf, buf_size, "%s)", detail);

            }

        }



        if (enc->width) {

            av_strlcat(buf, new_line ? separator : ", ", buf_size);



            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     "%dx%d",

                     enc->width, enc->height);



            if (av_log_get_level() >= AV_LOG_VERBOSE &&

                (enc->width != enc->coded_width ||

                 enc->height != enc->coded_height))

                snprintf(buf + strlen(buf), buf_size - strlen(buf),

                         " (%dx%d)", enc->coded_width, enc->coded_height);



            if (enc->sample_aspect_ratio.num) {

                av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,

                          enc->width * enc->sample_aspect_ratio.num,

                          enc->height * enc->sample_aspect_ratio.den,

                          1024 * 1024);

                snprintf(buf + strlen(buf), buf_size - strlen(buf),

                         " [SAR %d:%d DAR %d:%d]",

                         enc->sample_aspect_ratio.num, enc->sample_aspect_ratio.den,

                         display_aspect_ratio.num, display_aspect_ratio.den);

            }

            if (av_log_get_level() >= AV_LOG_DEBUG) {

                int g = av_gcd(enc->time_base.num, enc->time_base.den);

                snprintf(buf + strlen(buf), buf_size - strlen(buf),

                         ", %d/%d",

                         enc->time_base.num / g, enc->time_base.den / g);

            }

        }

        if (encode) {

            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     ", q=%d-%d", enc->qmin, enc->qmax);

        } else {

            if (enc->properties & FF_CODEC_PROPERTY_CLOSED_CAPTIONS)

                snprintf(buf + strlen(buf), buf_size - strlen(buf),

                         ", Closed Captions");

            if (enc->properties & FF_CODEC_PROPERTY_LOSSLESS)

                snprintf(buf + strlen(buf), buf_size - strlen(buf),

                         ", lossless");

        }

        break;

    case AVMEDIA_TYPE_AUDIO:

        av_strlcat(buf, separator, buf_size);



        if (enc->sample_rate) {

            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     "%d Hz, ", enc->sample_rate);

        }

        av_get_channel_layout_string(buf + strlen(buf), buf_size - strlen(buf), enc->channels, enc->channel_layout);

        if (enc->sample_fmt != AV_SAMPLE_FMT_NONE) {

            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     ", %s", av_get_sample_fmt_name(enc->sample_fmt));

        }

        if (   enc->bits_per_raw_sample > 0

            && enc->bits_per_raw_sample != av_get_bytes_per_sample(enc->sample_fmt) * 8)

            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     " (%d bit)", enc->bits_per_raw_sample);

        break;

    case AVMEDIA_TYPE_DATA:

        if (av_log_get_level() >= AV_LOG_DEBUG) {

            int g = av_gcd(enc->time_base.num, enc->time_base.den);

            if (g)

                snprintf(buf + strlen(buf), buf_size - strlen(buf),

                         ", %d/%d",

                         enc->time_base.num / g, enc->time_base.den / g);

        }

        break;

    case AVMEDIA_TYPE_SUBTITLE:

        if (enc->width)

            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     ", %dx%d", enc->width, enc->height);

        break;

    default:

        return;

    }

    if (encode) {

        if (enc->flags & AV_CODEC_FLAG_PASS1)

            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     ", pass 1");

        if (enc->flags & AV_CODEC_FLAG_PASS2)

            snprintf(buf + strlen(buf), buf_size - strlen(buf),

                     ", pass 2");

    }

    bitrate = get_bit_rate(enc);

    if (bitrate != 0) {

        snprintf(buf + strlen(buf), buf_size - strlen(buf),

                 ", %"PRId64" kb/s", bitrate / 1000);

    } else if (enc->rc_max_rate > 0) {

        snprintf(buf + strlen(buf), buf_size - strlen(buf),

                 ", max. %"PRId64" kb/s", (int64_t)enc->rc_max_rate / 1000);

    }

}
