首页 > 系统相关 >Windows下ffmpeg调用测试(YUV420P编码)

Windows下ffmpeg调用测试(YUV420P编码)

时间:2023-09-20 16:02:40浏览次数:71  
标签:ffmpeg pkt Windows frame ret codec YUV420P av data

1下载静态库和动态库

如果你是动态加载,可以直接使用动态库(dlopen等);否则就才用动态+ 静态的方式(动态库的静态加载方式);或者直接将静态库编译到你的执行程序(纯静态组件使用);

https://www.gyan.dev/ffmpeg/builds/#libraries

 添加组件

vs2022:  属性->c/c++->附加包含目录;将头文件目录添加进去

 属性->链接器->附加库目录,添加静态库路径;然后运行的时候记得吧dll放到EXE目录

 

 2 .YUV420P 编码264 

选择YUV420P(YV12)是因为,这个数据我可以通过FFmpeg命令行解析文件得到,用来测试,而且planner格式的数据Y,V,U是连续且单独放置的,不会存在UV交叉;YUV一帧的数据量就是width*heigt*1.5

随便找一个MP4录像,用FFmpeg命令行得到YUV数据,用来测试,ffmpeg -i input.mp4 -vf "format=yuv420p" output.yuv;如果你本身就有YUV测试数据,或者数据来源于实时的录像,截屏等等,就可以直接用;

下边的是FFmpeg提供的测试demo的源码,是自己生成的YUV,然后设置编码参数,输出264;我后边会根据这个demo进行一点点改动;不过最主要还是使用这个demo

/*
 * Copyright (c) 2001 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * @file libavcodec encoding video API usage example
 * @example encode_video.c
 *
 * Generate synthetic video data and encode it to an output file.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <libavcodec/avcodec.h>

#include <libavutil/opt.h>
#include <libavutil/imgutils.h>

static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
                   FILE *outfile)
{
    int ret;

    /* send the frame to the encoder */
    if (frame)
        printf("Send frame %3"PRId64"\n", frame->pts);

    ret = avcodec_send_frame(enc_ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending a frame for encoding\n");
        exit(1);
    }

    while (ret >= 0) {
        ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during encoding\n");
            exit(1);
        }

        printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
        fwrite(pkt->data, 1, pkt->size, outfile);
        av_packet_unref(pkt);
    }
}

int main(int argc, char **argv)
{
    const char *filename, *codec_name;
    const AVCodec *codec;
    AVCodecContext *c= NULL;
    int i, ret, x, y;
    FILE *f;
    AVFrame *frame;
    AVPacket *pkt;
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };

    if (argc <= 2) {
        fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]);
        exit(0);
    }
    filename = argv[1];
    codec_name = argv[2];

    /* find the mpeg1video encoder */
    codec = avcodec_find_encoder_by_name(codec_name);
    if (!codec) {
        fprintf(stderr, "Codec '%s' not found\n", codec_name);
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }

    pkt = av_packet_alloc();
    if (!pkt)
        exit(1);

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 352;
    c->height = 288;
    /* frames per second */
    c->time_base = (AVRational){1, 25};
    c->framerate = (AVRational){25, 1};

    /* emit one intra frame every ten frames
     * check frame pict_type before passing frame
     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
     * then gop_size is ignored and the output of encoder
     * will always be I frame irrespective to gop_size
     */
    c->gop_size = 10;
    c->max_b_frames = 1;
    c->pix_fmt = AV_PIX_FMT_YUV420P;

    if (codec->id == AV_CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);

    /* open it */
    ret = avcodec_open2(c, codec, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
        exit(1);
    }

    f = fopen(filename, "wb");
    if (!f) {
        fprintf(stderr, "Could not open %s\n", filename);
        exit(1);
    }

    frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width  = c->width;
    frame->height = c->height;

    ret = av_frame_get_buffer(frame, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate the video frame data\n");
        exit(1);
    }

    /* encode 1 second of video */
    for (i = 0; i < 25; i++) {
        fflush(stdout);

        /* Make sure the frame data is writable.
           On the first round, the frame is fresh from av_frame_get_buffer()
           and therefore we know it is writable.
           But on the next rounds, encode() will have called
           avcodec_send_frame(), and the codec may have kept a reference to
           the frame in its internal structures, that makes the frame
           unwritable.
           av_frame_make_writable() checks that and allocates a new buffer
           for the frame only if necessary.
         */
        ret = av_frame_make_writable(frame);
        if (ret < 0)
            exit(1);

        /* Prepare a dummy image.
           In real code, this is where you would have your own logic for
           filling the frame. FFmpeg does not care what you put in the
           frame.
         */
        /* Y */
        for (y = 0; y < c->height; y++) {
            for (x = 0; x < c->width; x++) {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }

        /* Cb and Cr */
        for (y = 0; y < c->height/2; y++) {
            for (x = 0; x < c->width/2; x++) {
                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
            }
        }

        frame->pts = i;

        /* encode the image */
        encode(c, frame, pkt, f);
    }

    /* flush the encoder */
    encode(c, NULL, pkt, f);

    /* Add sequence end code to have a real MPEG file.
       It makes only sense because this tiny examples writes packets
       directly. This is called "elementary stream" and only works for some
       codecs. To create a valid file, you usually need to write packets
       into a proper file format or protocol; see mux.c.
     */
    if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO)
        fwrite(endcode, 1, sizeof(endcode), f);
    fclose(f);

    avcodec_free_context(&c);
    av_frame_free(&frame);
    av_packet_free(&pkt);

    return 0;
}

  


 

函数介绍 

1  查找编码器;还可以使用AVcodec_find_encoder(condec_ID)

 const AVCodec*  codec = avcodec_find_encoder_by_name(codec_name);//codec_name = "libx264";

函数返回的AVCodec结构体指针,内部包含编码ID,支持的帧率,支持的像素格式,音频采样率,声道,编码档次等

 1 /**
 2  * AVCodec.
 3  */
 4 typedef struct AVCodec {
 5     /**
 6      * Name of the codec implementation.
 7      * The name is globally unique among encoders and among decoders (but an
 8      * encoder and a decoder can share the same name).
 9      * This is the primary way to find a codec from the user perspective.
10      */
11     const char *name;
12     /**
13      * Descriptive name for the codec, meant to be more human readable than name.
14      * You should use the NULL_IF_CONFIG_SMALL() macro to define it.
15      */
16     const char *long_name;
17     enum AVMediaType type;
18     enum AVCodecID id;
19     /**
20      * Codec capabilities.
21      * see AV_CODEC_CAP_*
22      */
23     int capabilities;
24     uint8_t max_lowres;                     ///< maximum value for lowres supported by the decoder
25     const AVRational *supported_framerates; ///< array of supported framerates, or NULL if any, array is terminated by {0,0}
26     const enum AVPixelFormat *pix_fmts;     ///< array of supported pixel formats, or NULL if unknown, array is terminated by -1
27     const int *supported_samplerates;       ///< array of supported audio samplerates, or NULL if unknown, array is terminated by 0
28     const enum AVSampleFormat *sample_fmts; ///< array of supported sample formats, or NULL if unknown, array is terminated by -1
29 #if FF_API_OLD_CHANNEL_LAYOUT
30     /**
31      * @deprecated use ch_layouts instead
32      */
33     attribute_deprecated
34     const uint64_t *channel_layouts;         ///< array of support channel layouts, or NULL if unknown. array is terminated by 0
35 #endif
36     const AVClass *priv_class;              ///< AVClass for the private context
37     const AVProfile *profiles;              ///< array of recognized profiles, or NULL if unknown, array is terminated by {FF_PROFILE_UNKNOWN}
38 
39     /**
40      * Group name of the codec implementation.
41      * This is a short symbolic name of the wrapper backing this codec. A
42      * wrapper uses some kind of external implementation for the codec, such
43      * as an external library, or a codec implementation provided by the OS or
44      * the hardware.
45      * If this field is NULL, this is a builtin, libavcodec native codec.
46      * If non-NULL, this will be the suffix in AVCodec.name in most cases
47      * (usually AVCodec.name will be of the form "<codec_name>_<wrapper_name>").
48      */
49     const char *wrapper_name;
50 
51     /**
52      * Array of supported channel layouts, terminated with a zeroed layout.
53      */
54     const AVChannelLayout *ch_layouts;
55 } AVCodec;

2  分配/创建 编码器上下文

作用就是创建上下文,设置编码参数;创建一个上下文之后,就可以设置一些参数了,这个参数会作用到编码器;

 AVCodecContext* c = NULL; c = avcodec_alloc_context3(codec);

  /* put sample parameters */
    c->bit_rate = 400000; //输出码率4M
    /* resolution must be a multiple of two */
    c->width = 1920; //输入的图像宽度,与YUV数据量对应上
    c->height = 1080;//输入图像的高
    /* frames per second */
    c->time_base.num = 1; 
    c->time_base.den = 25;
    c->framerate.num = 25; //25 FPS
    c->framerate.den = 1;

    /* emit one intra frame every ten frames
     * check frame pict_type before passing frame
     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
     * then gop_size is ignored and the output of encoder
     * will always be I frame irrespective to gop_size
     */
    c->gop_size = 10; //GOP 大小是10帧
    c->max_b_frames = 1;//每个I、P帧之间最多插入1个B帧
    c->pix_fmt = AV_PIX_FMT_YUV420P;//YV 12 planner格式;YVU连续且不存在UV交叉的一种存储格式

3  初始化编码器上下文,在上边第二步创建,设置参数后,初始化上下文,打开编码器

avcodec_open2(c, codec, NULL[用户自定义编码选项]);//const AVCodec* codec;    AVCodecContext* c = NULL;

4  创建frame,和package结构 用于承载数据

未压缩的图像放在frame结构体里,编码后的数据放到package结构体里;并不是所有的开源代码里frame存的都是未压缩数据,这个依照具体情况而定;在本博客的测试用例中frame存的是未压缩的YUV数据;有些地方frame存的是264,265数据,使用场景不同,意义也不一样

ffmpeg中的data存储未压缩数据,可以存储平铺模式planner,也可以存(交叉存储)的数据;

  frame = av_frame_alloc();

  pkt = av_packet_alloc();

 frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;//颜色格式,可设置YUV420P
    frame->width = c->width;
    frame->height = c->height;

    ret = av_frame_get_buffer(frame, 0);//后边每次复用buffer来装YUV之前,要先保证buffer没被占用,是可写的,av_frame_make_writable
    if (ret < 0) {
        fprintf(stderr, "Could not allocate the video frame data\n");
        exit(1);
    }

5 读取YUV数据,放到frame的data里边,编码;注意这里的输入输出缓冲都是复用的,是一个 读-编码-输出,串行逻辑

 int res_len = fread(buffer,len ,1,fpin);
       if (res_len > 0)
       {
           frame->data[0] = buffer;//Y分量
           frame->data[2] =buffer + frame->width * frame->height;//V分量
           frame->data[1] = buffer + frame->width * frame->height * 5 / 4;//U 分量
           frame->pts += 40;//显示时间戳
//frame 还可以设置该帧要不要编码成关键帧,帧类型等;
/* encode the image */ encode(c, frame, pkt, frle_out_ptr); }

5  AVpackage用来保存编码后的数据,如果H264编码,那这里就是H264的NAL数据,也就是ES流,内部还会保存当前帧的PTS,DTS

   编码函数的实现是,送YUV数据,获取Package: avcodec_send_frame(enc_ctx, frame);   avcodec_receive_packet(enc_ctx, pkt);

   将数据写到文件,解除对package的引用:fwrite(pkt->data, 1, pkt->size, outfile);   av_packet_unref(pkt);

typedef struct AVPacket {
    /**
     * A reference to the reference-counted buffer where the packet data is
     * stored.
     * May be NULL, then the packet data is not reference-counted.
     */
    AVBufferRef *buf;
    /**
     * Presentation timestamp in AVStream->time_base units; the time at which
     * the decompressed packet will be presented to the user.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     * pts MUST be larger or equal to dts as presentation cannot happen before
     * decompression, unless one wants to view hex dumps. Some formats misuse
     * the terms dts and pts/cts to mean something different. Such timestamps
     * must be converted to true pts/dts before they are stored in AVPacket.
     */
    int64_t pts;
    /**
     * Decompression timestamp in AVStream->time_base units; the time at which
     * the packet is decompressed.
     * Can be AV_NOPTS_VALUE if it is not stored in the file.
     */
    int64_t dts;
    uint8_t *data;
    int   size;
    int   stream_index;
    /**
     * A combination of AV_PKT_FLAG values
     */
    int   flags;
    /**
     * Additional packet data that can be provided by the container.
     * Packet can contain several types of side information.
     */
    AVPacketSideData *side_data;
    int side_data_elems;

    /**
     * Duration of this packet in AVStream->time_base units, 0 if unknown.
     * Equals next_pts - this_pts in presentation order.
     */
    int64_t duration;

    int64_t pos;                            ///< byte position in stream, -1 if unknown

    /**
     * for some private data of the user
     */
    void *opaque;

    /**
     * AVBufferRef for free use by the API user. FFmpeg will never check the
     * contents of the buffer ref. FFmpeg calls av_buffer_unref() on it when
     * the packet is unreferenced. av_packet_copy_props() calls create a new
     * reference with av_buffer_ref() for the target packet's opaque_ref field.
     *
     * This is unrelated to the opaque field, although it serves a similar
     * purpose.
     */
    AVBufferRef *opaque_ref;

    /**
     * Time base of the packet's timestamps.
     * In the future, this field may be set on packets output by encoders or
     * demuxers, but its value will be by default ignored on input to decoders
     * or muxers.
     */
    AVRational time_base;
} AVPacket;

6 编码完之后要再次调用下空数据的编码。以防有数据在编码器中未刷新出来

/* flush the encoder */
encode(c, NULL, pkt, fout);

并在编码输出文件结尾添加上mpeg的结束标记 uint8_t endcode[] = { 0, 0, 1, 0xb7 };

7 最后就是释放上下文,释放frame,package,关闭文件

avcodec_free_context(&c);
av_frame_free(&frame);
av_packet_free(&pkt);


 

下边提供一个真实可以编码的例子:(visual studio 2022)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>

char av_error[AV_ERROR_MAX_STRING_SIZE] = { 0 };
#define av_err2str(errnum) av_make_error_string(av_error, AV_ERROR_MAX_STRING_SIZE, errnum)


static void encode(AVCodecContext* enc_ctx, AVFrame* frame, AVPacket* pkt,
    FILE* outfile)
{
    int ret;

    /* send the frame to the encoder */
    if (frame)
        printf("Send frame %3ld\n", frame->pts);

    ret = avcodec_send_frame(enc_ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending a frame for encoding\n");
        exit(1);
    }

    while (ret >= 0) {
        ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error during encoding\n");
            exit(1);
        }

        printf("Write packet %3ld (size=%5d)\n", pkt->pts, pkt->size);
        fwrite(pkt->data, 1, pkt->size, outfile);
        av_packet_unref(pkt);
    }
}

int main(int argc, char** argv)
{
    const char* filename, * codec_name,* filename_in;
    //
    const AVCodec* codec;
    AVCodecContext* c = NULL;
    int i, ret, x, y;
    FILE* f;
    AVFrame* frame;
    AVPacket* pkt;
    uint8_t endcode[] = { 0, 0, 1, 0xb7 };
    int len = 1920 * 1080 * 3 / 2;
    uint8_t* buffer = new uint8_t[len];

   
    filename = "D:/Emscripten/cmaketest/20230801230523.264";//编码输出的264,文件没有会自动创建
    filename_in = "D:/Emscripten/cmaketest/20230.yuv";//待编码的YUV,YV12;需要有
    codec_name = "libx264";//可以自己指定其他编码器
    
    FILE* fpin = fopen(filename_in, "rb+");
    if (!fpin)
    {
        fprintf(stderr, "Codec '%s' not open\n",filename_in);
        exit(1);
    }

    //查找编码器;还可以使用AVcodec_find_encoder(condec_ID)
    codec = avcodec_find_encoder_by_name(codec_name);
    if (!codec) {
        fprintf(stderr, "Codec '%s' not found\n", codec_name);
        exit(1);
    }

    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate video codec context\n");
        exit(1);
    }

    pkt = av_packet_alloc();
    if (!pkt)
        exit(1);

    /* put sample parameters */
    c->bit_rate = 400000;
    /* resolution must be a multiple of two */
    c->width = 1920;
    c->height = 1080;
    /* frames per second */
    c->time_base.num = 1;
    c->time_base.den = 25;
    c->framerate.num = 25;
    c->framerate.den = 1;

    /* emit one intra frame every ten frames
     * check frame pict_type before passing frame
     * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
     * then gop_size is ignored and the output of encoder
     * will always be I frame irrespective to gop_size
     */
    c->gop_size = 10;
    c->max_b_frames = 1;
    c->pix_fmt = AV_PIX_FMT_YUV420P;//YV 12 格式

    if (codec->id == AV_CODEC_ID_H264)
        av_opt_set(c->priv_data, "preset", "slow", 0);

    /* open it */
    ret = avcodec_open2(c, codec, NULL);
    if (ret < 0) {
        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
        exit(1);
    }

    f = fopen(filename, "wb");
    if (!f) {
        fprintf(stderr, "Could not open %s\n", filename);
        exit(1);
    }

    frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr, "Could not allocate video frame\n");
        exit(1);
    }
    frame->format = c->pix_fmt;
    frame->width = c->width;
    frame->height = c->height;

    ret = av_frame_get_buffer(frame, 0);
    if (ret < 0) {
        fprintf(stderr, "Could not allocate the video frame data\n");
        exit(1);
    }

    /* encode 1 second of video */
    while (!feof(fpin)) {
       
        fflush(stdout);

        /* Make sure the frame data is writable.
           On the first round, the frame is fresh from av_frame_get_buffer()
           and therefore we know it is writable.
           But on the next rounds, encode() will have called
           avcodec_send_frame(), and the codec may have kept a reference to
           the frame in its internal structures, that makes the frame
           unwritable.
           av_frame_make_writable() checks that and allocates a new buffer
           for the frame only if necessary.
         */
        ret = av_frame_make_writable(frame);
        if (ret < 0)
            exit(1);

        /* Prepare a dummy image.
           In real code, this is where you would have your own logic for
           filling the frame. FFmpeg does not care what you put in the
           frame.
         */
         /* Y */
       int res_len = fread(buffer,len ,1,fpin);
       if (res_len > 0)
       {
           frame->data[0] = buffer;
           frame->data[2] =buffer + frame->width * frame->height;
           frame->data[1] = buffer + frame->width * frame->height * 5 / 4;
           frame->pts += 40;

           /* encode the image */
           encode(c, frame, pkt, f);
       }
    }

    /* flush the encoder */
    encode(c, NULL, pkt, f);
    if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO)
        fwrite(endcode, 1, sizeof(endcode), f);
    fclose(f);

    avcodec_free_context(&c);
    av_frame_free(&frame);
    av_packet_free(&pkt);

    delete[] buffer;
    fclose(fpin);
    return 0;
}
}

效果:

 264数据用elecard打开:

 这个是我修改 gop =25;无B帧的情况,编码后的数据

 

标签:ffmpeg,pkt,Windows,frame,ret,codec,YUV420P,av,data
From: https://www.cnblogs.com/8335IT/p/17717288.html

相关文章

  • 解决Windows11家庭版无法连接网络打印机问题
    Win11更新后连接不上网络打印机,该怎么办呢?方法一:修改组策略1、打开本地组策略-管理模板-打印机 2、找到配置RPC连接设置,打开 3、选择“已启用”,将下面连接协议改成“命名管道上的RPC”,搞定。 方法二:添加网络凭据1、打开控制面板-->用户账户 -->管理Windows凭据......
  • Windows10、Windows11家庭版开启组策略编辑器
    win10家庭版默认是不开启本地组策略功能的,这就限制了我们对win10系统的修改,所以对于喜欢折腾电脑的朋友来说就比较喜欢把电脑系统重装为比win10家庭版更高级的版本,比如专业版,企业版。但是,由于笔记本电脑预安装的基本为win10家庭版系统,且作为原版系统,普通用户通常是不会选择重装系......
  • windows下设置goland的output directory
    goland中,想要改变gobuild-o的输出路径,不再往c盘里输出,可以按照下面设置        ......
  • windows下elasticsearch安装完无法访问9200的问题
    问题描述:windows系统下启动成功,但无法访问http://localhost:9200/系统环境:操作系统:WindowsServer2022DatacenterJDK版本:jdk-8u381-windows-x64.exeElasticsearch版本:elasticsearch-8.10.1-windows-x86_64.zip注:Elasticsearch最低要求JDK1.8,下载地址:https://www.elastic.co......
  • 当你的计算机开机后直接跳过了引导界面,而直接进入Windows界面,这可能是由于以下几种启
    当你的计算机开机后直接跳过了引导界面,而直接进入Windows界面,这可能是由于以下几种启动故障之一导致的:引导顺序错误:在计算机引导时,硬盘、光驱、USB等设备的启动顺序是有优先级的。如果设置不正确,计算机可能会跳过引导界面而直接选择第一个可引导设备,通常是硬盘。你可以进入计算机......
  • M2芯片MAC安装windows虚拟机
    安装windows虚拟机MAC虚拟软件用的是VMwareFusionpro13及更高版本,使用的镜像是ARM的,X64的不能用。在虚拟机启动时,出现以下界面1-2秒后按下f2,进入安装系统界面,否则会出现报错StartPXEoverIPv4安装windows系统,因为默认安装在连接网络那一步无法选择网络,所以在出现选择国家选......
  • Windows系统快捷方式图标变成白色方块解决方法
    Windows系统快捷方式图标变成白色解决如图所示解决方法:1、打开文件夹(任意),点击【查看】菜单,然后勾选【隐藏的项目】;2、同时按下【Win】+【R】两个按键,在打开的【运行】窗口中输入%localappdata%;3、在打开的文件夹中,找到【Iconcache.db】,将其删除;4、在任务栏......
  • Windows-Sqlserver2016对指定数据库进行扩容
    前言:之所以会想起来写这一篇文章,是因为工作中正好需要用到,所以记录一下如何对想要的数据库进行扩容操作实际上在处理这种问题之前,我翻阅了许多文章,也没找到自己想要的答案,也正因为如此打算自己写一篇关于扩容数据库的操作文章 搭建实验环境:在扩容之前,我们先创建一个数据库......
  • Windows server 2022安装配置——WSL2 访问
    从局域网访问wsl2首先必须得知道这两个ip的含义。在windows下执行wslhostname-i 命令,是通过WSL2安装的Linux分发版IP地址(WSL2VM的地址)在linux子系统下执行cat/etc/resolv.conf 命令,是表示从WSL2子系统看到的WINDOWS系统的IP地址(WSL2VM)WSL2......
  • windows将frp添加到服务,并后台运行
    下载nssmhttp://www.nssm.cc/download添加frpc到windows服务nssminstallfrpc"C:/frpc/frpc.exe"nssmsetfrpcAppParameters"-cC:/frpc/frpc.ini"启动服务netstartfrpc......