FFmpeg源代码简单分析-通用-常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

参考链接

  • FFmpeg源代码简单分析:常见结构体的初始化和销毁(AVFormatContext,AVFrame等)_雷霄骅的博客-CSDN博客

结构体

  • AVFormatContext:统领全局的基本结构体。主要用于处理封装格式(FLV/MKV/RMVB等)
    • FFmpeg: AVFormatContext Struct Reference

  • AVIOContext:输入输出对应的结构体,用于输入输出(读写文件,RTMP协议等)   
    • FFmpeg: AVIOContext Struct Reference
  • AVStream:视音频流对应的结构体 
    • FFmpeg: AVStream Struct Reference
  • AVCodecContext:音视频编解码结构体
    • FFmpeg: AVCodecContext Struct Reference
  • AVFrame:存储非压缩的数据(视频对应RGB/YUV像素数据,音频对应PCM采样数据)
    • https://ffmpeg.org/doxygen/trunk/structAVFrame.html
  • AVPacket:存储压缩数据(视频对应H.264等码流数据,音频对应AAC/MP3等码流数据)
    • https://ffmpeg.org/doxygen/trunk/structAVPacket.html
结构体初始化销毁
AVFormatContextavformat_alloc_contextavformat_free_context
AVIOContextavio_alloc_contextavio_context_free
AVStreamavformat_new_streamavformat_free_context
AVCodecContextavcodec_alloc_context3avcodec_free_context
AVPacket

av_init_packet()

av_new_packet

av_packet_free
AVFrame

av_frame_alloc

av_image_fill_arrays

av_frame_free

初始化

  • avformat_alloc_context()
    • FFmpeg: Core functions
AVFormatContext *avformat_alloc_context(void)
{FFFormatContext *const si = av_mallocz(sizeof(*si));AVFormatContext *s;if (!si)return NULL;s = &si->pub;s->av_class = &av_format_context_class;s->io_open  = io_open_default;s->io_close = ff_format_io_close_default;s->io_close2= io_close2_default;av_opt_set_defaults(s);si->pkt = av_packet_alloc();si->parse_pkt = av_packet_alloc();if (!si->pkt || !si->parse_pkt) {avformat_free_context(s);return NULL;}si->shortest_end = AV_NOPTS_VALUE;return s;
}
  •  使用av_opt_set_defaults函数给字段设置默认值
void av_opt_set_defaults(void *s)
{av_opt_set_defaults2(s, 0, 0);
}void av_opt_set_defaults2(void *s, int mask, int flags)
{const AVOption *opt = NULL;while ((opt = av_opt_next(s, opt))) {void *dst = ((uint8_t*)s) + opt->offset;if ((opt->flags & mask) != flags)continue;if (opt->flags & AV_OPT_FLAG_READONLY)continue;switch (opt->type) {case AV_OPT_TYPE_CONST:/* Nothing to be done here */break;case AV_OPT_TYPE_BOOL:case AV_OPT_TYPE_FLAGS:case AV_OPT_TYPE_INT:case AV_OPT_TYPE_INT64:case AV_OPT_TYPE_UINT64:case AV_OPT_TYPE_DURATION:
#if FF_API_OLD_CHANNEL_LAYOUT
FF_DISABLE_DEPRECATION_WARNINGScase AV_OPT_TYPE_CHANNEL_LAYOUT:
FF_ENABLE_DEPRECATION_WARNINGS
#endifcase AV_OPT_TYPE_PIXEL_FMT:case AV_OPT_TYPE_SAMPLE_FMT:write_number(s, opt, dst, 1, 1, opt->default_val.i64);break;case AV_OPT_TYPE_DOUBLE:case AV_OPT_TYPE_FLOAT: {double val;val = opt->default_val.dbl;write_number(s, opt, dst, val, 1, 1);}break;case AV_OPT_TYPE_RATIONAL: {AVRational val;val = av_d2q(opt->default_val.dbl, INT_MAX);write_number(s, opt, dst, 1, val.den, val.num);}break;case AV_OPT_TYPE_COLOR:set_string_color(s, opt, opt->default_val.str, dst);break;case AV_OPT_TYPE_STRING:set_string(s, opt, opt->default_val.str, dst);break;case AV_OPT_TYPE_IMAGE_SIZE:set_string_image_size(s, opt, opt->default_val.str, dst);break;case AV_OPT_TYPE_VIDEO_RATE:set_string_video_rate(s, opt, opt->default_val.str, dst);break;case AV_OPT_TYPE_BINARY:set_string_binary(s, opt, opt->default_val.str, dst);break;case AV_OPT_TYPE_CHLAYOUT:set_string_channel_layout(s, opt, opt->default_val.str, dst);break;case AV_OPT_TYPE_DICT:set_string_dict(s, opt, opt->default_val.str, dst);break;default:av_log(s, AV_LOG_DEBUG, "AVOption type %d of option %s not implemented yet\n",opt->type, opt->name);}}
}
  • avio_alloc_context()
    • FFmpeg: libavformat/avio.h File Reference
    • 使用av_malloc为FFIOContest进行内存分配
    • 再次调用ffio_init_context完成初始化
AVIOContext *avio_alloc_context(unsigned char *buffer,int buffer_size,int write_flag,void *opaque,int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),int64_t (*seek)(void *opaque, int64_t offset, int whence))
{FFIOContext *s = av_malloc(sizeof(*s));if (!s)return NULL;ffio_init_context(s, buffer, buffer_size, write_flag, opaque,read_packet, write_packet, seek);return &s->pub;
}
  •  ffio_init_context对FFIOContest中的缓存,函数指针等等进行了赋值
void ffio_init_context(FFIOContext *ctx,unsigned char *buffer,int buffer_size,int write_flag,void *opaque,int (*read_packet)(void *opaque, uint8_t *buf, int buf_size),int (*write_packet)(void *opaque, uint8_t *buf, int buf_size),int64_t (*seek)(void *opaque, int64_t offset, int whence))
{AVIOContext *const s = &ctx->pub;memset(ctx, 0, sizeof(*ctx));s->buffer      = buffer;ctx->orig_buffer_size =s->buffer_size = buffer_size;s->buf_ptr     = buffer;s->buf_ptr_max = buffer;s->opaque      = opaque;s->direct      = 0;url_resetbuf(s, write_flag ? AVIO_FLAG_WRITE : AVIO_FLAG_READ);s->write_packet    = write_packet;s->read_packet     = read_packet;s->seek            = seek;s->pos             = 0;s->eof_reached     = 0;s->error           = 0;s->seekable        = seek ? AVIO_SEEKABLE_NORMAL : 0;s->min_packet_size = 0;s->max_packet_size = 0;s->update_checksum = NULL;ctx->short_seek_threshold = SHORT_SEEK_THRESHOLD;if (!read_packet && !write_flag) {s->pos     = buffer_size;s->buf_end = s->buffer + buffer_size;}s->read_pause = NULL;s->read_seek  = NULL;s->write_data_type       = NULL;s->ignore_boundary_point = 0;ctx->current_type        = AVIO_DATA_MARKER_UNKNOWN;ctx->last_time           = AV_NOPTS_VALUE;ctx->short_seek_get      = NULL;
#if FF_API_AVIOCONTEXT_WRITTEN
FF_DISABLE_DEPRECATION_WARNINGSs->written               = 0;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
}
  • avformat_new_stream()
    • FFmpeg: Core functions
AVStream *avformat_new_stream(AVFormatContext *s, const AVCodec *c)
{FFFormatContext *const si = ffformatcontext(s);FFStream *sti;AVStream *st;AVStream **streams;if (s->nb_streams >= s->max_streams) {av_log(s, AV_LOG_ERROR, "Number of streams exceeds max_streams parameter"" (%d), see the documentation if you wish to increase it\n",s->max_streams);return NULL;}streams = av_realloc_array(s->streams, s->nb_streams + 1, sizeof(*streams));if (!streams)return NULL;s->streams = streams;sti = av_mallocz(sizeof(*sti));if (!sti)return NULL;st = &sti->pub;#if FF_API_AVSTREAM_CLASSst->av_class = &stream_class;
#endifst->codecpar = avcodec_parameters_alloc();if (!st->codecpar)goto fail;sti->avctx = avcodec_alloc_context3(NULL);if (!sti->avctx)goto fail;if (s->iformat) {sti->info = av_mallocz(sizeof(*sti->info));if (!sti->info)goto fail;#if FF_API_R_FRAME_RATEsti->info->last_dts      = AV_NOPTS_VALUE;
#endifsti->info->fps_first_dts = AV_NOPTS_VALUE;sti->info->fps_last_dts  = AV_NOPTS_VALUE;/* default pts setting is MPEG-like */avpriv_set_pts_info(st, 33, 1, 90000);/* we set the current DTS to 0 so that formats without any timestamps* but durations get some timestamps, formats with some unknown* timestamps have their first few packets buffered and the* timestamps corrected before they are returned to the user */sti->cur_dts = RELATIVE_TS_BASE;} else {sti->cur_dts = AV_NOPTS_VALUE;}st->index      = s->nb_streams;st->start_time = AV_NOPTS_VALUE;st->duration   = AV_NOPTS_VALUE;sti->first_dts     = AV_NOPTS_VALUE;sti->probe_packets = s->max_probe_packets;sti->pts_wrap_reference = AV_NOPTS_VALUE;sti->pts_wrap_behavior  = AV_PTS_WRAP_IGNORE;sti->last_IP_pts = AV_NOPTS_VALUE;sti->last_dts_for_order_check = AV_NOPTS_VALUE;for (int i = 0; i < MAX_REORDER_DELAY + 1; i++)sti->pts_buffer[i] = AV_NOPTS_VALUE;st->sample_aspect_ratio = (AVRational) { 0, 1 };sti->inject_global_side_data = si->inject_global_side_data;sti->need_context_update = 1;s->streams[s->nb_streams++] = st;return st;
fail:ff_free_stream(&st);return NULL;
}
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
{AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));if (!avctx)return NULL;if (init_context_defaults(avctx, codec) < 0) {av_free(avctx);return NULL;}return avctx;
}
static int init_context_defaults(AVCodecContext *s, const AVCodec *codec)
{const FFCodec *const codec2 = ffcodec(codec);int flags=0;memset(s, 0, sizeof(AVCodecContext));s->av_class = &av_codec_context_class;s->codec_type = codec ? codec->type : AVMEDIA_TYPE_UNKNOWN;if (codec) {s->codec = codec;s->codec_id = codec->id;}if(s->codec_type == AVMEDIA_TYPE_AUDIO)flags= AV_OPT_FLAG_AUDIO_PARAM;else if(s->codec_type == AVMEDIA_TYPE_VIDEO)flags= AV_OPT_FLAG_VIDEO_PARAM;else if(s->codec_type == AVMEDIA_TYPE_SUBTITLE)flags= AV_OPT_FLAG_SUBTITLE_PARAM;av_opt_set_defaults2(s, flags, flags);av_channel_layout_uninit(&s->ch_layout);s->time_base           = (AVRational){0,1};s->framerate           = (AVRational){ 0, 1 };s->pkt_timebase        = (AVRational){ 0, 1 };s->get_buffer2         = avcodec_default_get_buffer2;s->get_format          = avcodec_default_get_format;s->get_encode_buffer   = avcodec_default_get_encode_buffer;s->execute             = avcodec_default_execute;s->execute2            = avcodec_default_execute2;s->sample_aspect_ratio = (AVRational){0,1};s->ch_layout.order     = AV_CHANNEL_ORDER_UNSPEC;s->pix_fmt             = AV_PIX_FMT_NONE;s->sw_pix_fmt          = AV_PIX_FMT_NONE;s->sample_fmt          = AV_SAMPLE_FMT_NONE;s->reordered_opaque    = AV_NOPTS_VALUE;if(codec && codec2->priv_data_size){s->priv_data = av_mallocz(codec2->priv_data_size);if (!s->priv_data)return AVERROR(ENOMEM);if(codec->priv_class){*(const AVClass**)s->priv_data = codec->priv_class;av_opt_set_defaults(s->priv_data);}}if (codec && codec2->defaults) {int ret;const FFCodecDefault *d = codec2->defaults;while (d->key) {ret = av_opt_set(s, d->key, d->value, 0);av_assert0(ret >= 0);d++;}}return 0;
}
  • avcodec_alloc_context3()
    • FFmpeg: Core functions/structures.
AVCodecContext *avcodec_alloc_context3(const AVCodec *codec)
{AVCodecContext *avctx= av_malloc(sizeof(AVCodecContext));if (!avctx)return NULL;if (init_context_defaults(avctx, codec) < 0) {av_free(avctx);return NULL;}return avctx;
}
  • av_init_packet()
#if FF_API_INIT_PACKET
void av_init_packet(AVPacket *pkt)
{pkt->pts                  = AV_NOPTS_VALUE;pkt->dts                  = AV_NOPTS_VALUE;pkt->pos                  = -1;pkt->duration             = 0;pkt->flags                = 0;pkt->stream_index         = 0;pkt->buf                  = NULL;pkt->side_data            = NULL;pkt->side_data_elems      = 0;pkt->opaque               = NULL;pkt->opaque_ref           = NULL;pkt->time_base            = av_make_q(0, 1);
}
#endif
  • av_new_packet()
    • FFmpeg: AVPacket
int av_new_packet(AVPacket *pkt, int size)
{AVBufferRef *buf = NULL;int ret = packet_alloc(&buf, size);if (ret < 0)return ret;get_packet_defaults(pkt);pkt->buf      = buf;pkt->data     = buf->data;pkt->size     = size;return 0;
}
static int packet_alloc(AVBufferRef **buf, int size)
{int ret;if (size < 0 || size >= INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE)return AVERROR(EINVAL);ret = av_buffer_realloc(buf, size + AV_INPUT_BUFFER_PADDING_SIZE);if (ret < 0)return ret;memset((*buf)->data + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);return 0;
}
static void get_packet_defaults(AVPacket *pkt)
{memset(pkt, 0, sizeof(*pkt));pkt->pts             = AV_NOPTS_VALUE;pkt->dts             = AV_NOPTS_VALUE;pkt->pos             = -1;pkt->time_base       = av_make_q(0, 1);
}
  • packet_alloc()中调用av_buffer_realloc()为AVPacket分配内存。然后调用memset()将分配的内存置0。 
  • av_frame_alloc()
    • FFmpeg: AVFrame
AVFrame *av_frame_alloc(void)
{AVFrame *frame = av_malloc(sizeof(*frame));if (!frame)return NULL;get_frame_defaults(frame);return frame;
}
static void get_frame_defaults(AVFrame *frame)
{memset(frame, 0, sizeof(*frame));frame->pts                   =frame->pkt_dts               = AV_NOPTS_VALUE;frame->best_effort_timestamp = AV_NOPTS_VALUE;frame->pkt_duration        = 0;frame->pkt_pos             = -1;frame->pkt_size            = -1;frame->time_base           = (AVRational){ 0, 1 };frame->key_frame           = 1;frame->sample_aspect_ratio = (AVRational){ 0, 1 };frame->format              = -1; /* unknown */frame->extended_data       = frame->data;frame->color_primaries     = AVCOL_PRI_UNSPECIFIED;frame->color_trc           = AVCOL_TRC_UNSPECIFIED;frame->colorspace          = AVCOL_SPC_UNSPECIFIED;frame->color_range         = AVCOL_RANGE_UNSPECIFIED;frame->chroma_location     = AVCHROMA_LOC_UNSPECIFIED;frame->flags               = 0;
}
  • 从av_frame_alloc()的代码可以看出,该函数并没有为AVFrame的像素数据分配空间。
  • 因此AVFrame中的像素数据需要自行分配空间,例如使用av_image_fill_arrays()等函数。
  • avpicture_fill() 弃用
  • av_image_fill_arrays()
    • FFmpeg: Image related
int av_image_fill_arrays(uint8_t *dst_data[4], int dst_linesize[4],const uint8_t *src, enum AVPixelFormat pix_fmt,int width, int height, int align)
{int ret, i;ret = av_image_check_size(width, height, 0, NULL);if (ret < 0)return ret;ret = av_image_fill_linesizes(dst_linesize, pix_fmt, width);if (ret < 0)return ret;for (i = 0; i < 4; i++)dst_linesize[i] = FFALIGN(dst_linesize[i], align);return av_image_fill_pointers(dst_data, pix_fmt, height, (uint8_t *)src, dst_linesize);
}
  • av_image_fill_arrays()函数中包含3个函数:av_image_check_size(),av_image_fill_linesizes(),av_image_fill_pointers()。
  • av_image_check_size()用于检查输入的宽高参数是否合理,即不能太大或者为负数。
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
{return av_image_check_size2(w, h, INT64_MAX, AV_PIX_FMT_NONE, log_offset, log_ctx);
}
int av_image_check_size2(unsigned int w, unsigned int h, int64_t max_pixels, enum AVPixelFormat pix_fmt, int log_offset, void *log_ctx)
{ImgUtils imgutils = {.class      = &imgutils_class,.log_offset = log_offset,.log_ctx    = log_ctx,};int64_t stride = av_image_get_linesize(pix_fmt, w, 0);if (stride <= 0)stride = 8LL*w;stride += 128*8;if ((int)w<=0 || (int)h<=0 || stride >= INT_MAX || stride*(uint64_t)(h+128) >= INT_MAX) {av_log(&imgutils, AV_LOG_ERROR, "Picture size %ux%u is invalid\n", w, h);return AVERROR(EINVAL);}if (max_pixels < INT64_MAX) {if (w*(int64_t)h > max_pixels) {av_log(&imgutils, AV_LOG_ERROR,"Picture size %ux%u exceeds specified max pixel count %"PRId64", see the documentation if you wish to increase it\n",w, h, max_pixels);return AVERROR(EINVAL);}}return 0;
}
  • av_image_fill_linesizes()用于填充dst_linesize。
int av_image_fill_linesizes(int linesizes[4], enum AVPixelFormat pix_fmt, int width)
{int i, ret;const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);int max_step     [4];       /* max pixel step for each plane */int max_step_comp[4];       /* the component for each plane which has the max pixel step */memset(linesizes, 0, 4*sizeof(linesizes[0]));if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL)return AVERROR(EINVAL);av_image_fill_max_pixsteps(max_step, max_step_comp, desc);for (i = 0; i < 4; i++) {if ((ret = image_get_linesize(width, i, max_step[i], max_step_comp[i], desc)) < 0)return ret;linesizes[i] = ret;}return 0;
}
  • av_image_fill_pointers()则用于填充dst_data。
int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height,uint8_t *ptr, const int linesizes[4])
{int i, ret;ptrdiff_t linesizes1[4];size_t sizes[4];memset(data     , 0, sizeof(data[0])*4);for (i = 0; i < 4; i++)linesizes1[i] = linesizes[i];ret = av_image_fill_plane_sizes(sizes, pix_fmt, height, linesizes1);if (ret < 0)return ret;ret = 0;for (i = 0; i < 4; i++) {if (sizes[i] > INT_MAX - ret)return AVERROR(EINVAL);ret += sizes[i];}if (!ptr)return ret;data[0] = ptr;for (i = 1; i < 4 && sizes[i]; i++)data[i] = data[i - 1] + sizes[i - 1];return ret;
}

销毁

  • avformat_free_context()
    • FFmpeg: Core functions
    • avformat_free_context调用了各式各样的销毁函数,av_opt_free() av_freep() av_dict_free()等,这些函数用于释放不同种类的变量
void avformat_free_context(AVFormatContext *s)
{FFFormatContext *si;if (!s)return;si = ffformatcontext(s);if (s->oformat && s->oformat->deinit && si->initialized)s->oformat->deinit(s);av_opt_free(s);if (s->iformat && s->iformat->priv_class && s->priv_data)av_opt_free(s->priv_data);if (s->oformat && s->oformat->priv_class && s->priv_data)av_opt_free(s->priv_data);for (unsigned i = 0; i < s->nb_streams; i++)ff_free_stream(&s->streams[i]);s->nb_streams = 0;for (unsigned i = 0; i < s->nb_programs; i++) {av_dict_free(&s->programs[i]->metadata);av_freep(&s->programs[i]->stream_index);av_freep(&s->programs[i]);}s->nb_programs = 0;av_freep(&s->programs);av_freep(&s->priv_data);while (s->nb_chapters--) {av_dict_free(&s->chapters[s->nb_chapters]->metadata);av_freep(&s->chapters[s->nb_chapters]);}av_freep(&s->chapters);av_dict_free(&s->metadata);av_dict_free(&si->id3v2_meta);av_packet_free(&si->pkt);av_packet_free(&si->parse_pkt);av_freep(&s->streams);ff_flush_packet_queue(s);av_freep(&s->url);av_free(s);
}

  • 此处查看释放AVStream的函数ff_free_stream()
  • 其与AVFormatContest类似,也是调用av_opt_free() av_freep() av_dict_free()等函数用于释放不同种类的变量
     
void ff_free_stream(AVStream **pst)
{AVStream *st = *pst;FFStream *const sti = ffstream(st);if (!st)return;for (int i = 0; i < st->nb_side_data; i++)av_freep(&st->side_data[i].data);av_freep(&st->side_data);if (st->attached_pic.data)av_packet_unref(&st->attached_pic);av_parser_close(sti->parser);avcodec_free_context(&sti->avctx);av_bsf_free(&sti->bsfc);av_freep(&sti->priv_pts);av_freep(&sti->index_entries);av_freep(&sti->probe_data.buf);av_bsf_free(&sti->extract_extradata.bsf);if (sti->info) {av_freep(&sti->info->duration_error);av_freep(&sti->info);}av_dict_free(&st->metadata);avcodec_parameters_free(&st->codecpar);av_freep(&st->priv_data);av_freep(pst);
}
  •  如果使用了parser,会调用av_parser_close()关闭parser
void av_parser_close(AVCodecParserContext *s)
{if (s) {if (s->parser->parser_close)s->parser->parser_close(s);av_freep(&s->priv_data);av_free(s);}
}
  • avio_context_free()
    • FFmpeg: libavformat/avio.h File Reference
  • avcodec_free_context()
    • FFmpeg: Core functions/structures.
  • av_frame_free()
    • FFmpeg: AVFrame
void av_frame_free(AVFrame **frame)
{if (!frame || !*frame)return;av_frame_unref(*frame);av_freep(frame);
}
  • 在释放AVFrame结构体之前,首先调用了一个函数av_frame_unref()。av_frame_unref()也是一个FFmpeg的API,它的作用是释放AVFrame中参考的缓存(还没完全弄懂),并且重置AVFrame中的字段。
  • 调用这个函数的目的应该是为了确保AVFrame可以被正常释放。
  • 代码如下
void av_frame_unref(AVFrame *frame)
{int i;if (!frame)return;wipe_side_data(frame);for (i = 0; i < FF_ARRAY_ELEMS(frame->buf); i++)av_buffer_unref(&frame->buf[i]);for (i = 0; i < frame->nb_extended_buf; i++)av_buffer_unref(&frame->extended_buf[i]);av_freep(&frame->extended_buf);av_dict_free(&frame->metadata);av_buffer_unref(&frame->hw_frames_ctx);av_buffer_unref(&frame->opaque_ref);av_buffer_unref(&frame->private_ref);if (frame->extended_data != frame->data)av_freep(&frame->extended_data);av_channel_layout_uninit(&frame->ch_layout);get_frame_defaults(frame);
}
  • av_packet_free()
  • 从代码可以看出,av_packet_free()调用av_packet_unref()释放AVPacket中的数据,
  • 调用了av_packet_free_side_data()释放了side_data(存储封装格式可以提供的额外的数据)。
void av_packet_free(AVPacket **pkt)
{if (!pkt || !*pkt)return;av_packet_unref(*pkt);av_freep(pkt);
}
void av_packet_unref(AVPacket *pkt)
{av_packet_free_side_data(pkt);av_buffer_unref(&pkt->opaque_ref);av_buffer_unref(&pkt->buf);get_packet_defaults(pkt);
}
请使用手机"扫一扫"x

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python中object转为float_object格式怎样无损转换成float64格式

这次给大家带来object格式怎样无损转换成float64格式&#xff0c;object格式无损转换成float64格式的注意事项有哪些&#xff0c;下面就是实战案例&#xff0c;一起来看一下。在数据处理过程中比如从CSV文件中导入数据data_df pd.read_csv("names.csv")在处理之前一…

FFmpeg源代码简单分析-通用-avio_open2()

参考链接 FFmpeg源代码简单分析&#xff1a;avio_open2()_雷霄骅的博客-CSDN博客_avio_open avio_open2() 该函数用于打开FFmpeg的输入输出文件avio_open2()的声明位于libavformat\avio.h文件中&#xff0c;如下所示。 /*** Create and initialize a AVIOContext for accessi…

用Tomcat构建一个简单图片服务器

前提条件 Tomcat 7.0.90 方法一&#xff1a;修改配置文件 在TOMCAT_HOME/conf/server.xml配置文件内的<Host>内添加一子标签&#xff1a; <Context docBase"C:\exambase\" path"/img"/>方法二&#xff1a;添加Servlet 新建一应用&#xf…

flash静态的农夫走路_健身神动作——你不知道的“农夫行走”

原标题&#xff1a;健身神动作——你不知道的“农夫行走”本期导读握力是训练中及其重要的一环&#xff0c;强大的握力会使你的训练效果MAX&#xff0c;就像开了加速器一样&#xff01;很多人把握力和前臂力量混为一谈&#xff0c;主要使用腕弯举提高握力。实际上&#xff0c;握…

FFmpeg源代码简单分析-通用-av_find_decoder()和av_find_encoder()

参考链接 FFmpeg源代码简单分析&#xff1a;av_find_decoder()和av_find_encoder()_雷霄骅的博客-CSDN博客_avcodec_find_encoder avcodec_find_encoder avcodec_find_encoder()用于查找FFmpeg的编码器avcodec_find_encoder()的声明位于libavcodec\codec.h 版本差异avcode…

用Java的Set实现交并差等集合运算

放码过来 package com.lun.util;import java.util.HashSet; import java.util.Set;public class SetUtils {public static <T> Set<T> union(Set<T> setA, Set<T> setB) {Set<T> tmp new HashSet<T>(setA);tmp.addAll(setB);return tmp;…

post方法就反回了一个string字符串前台怎么接_Golang Web入门(2):如何实现一个RESTful风格的路由...

摘要在上一篇文章中&#xff0c;我们聊了聊在Golang中怎么实现一个Http服务器。但是在最后我们可以发现&#xff0c;固然DefaultServeMux可以做路由分发的功能&#xff0c;但是他的功能同样是不完善的。由DefaultServeMux做路由分发&#xff0c;是不能实现RESTful风格的API的&a…

FFmpeg源代码简单分析-通用-avcodec_open2()

参考链接 FFmpeg源代码简单分析&#xff1a;avcodec_open2()_雷霄骅的博客-CSDN博客 avcodec_open2() 该函数用于初始化一个音视频编解码器的AVCodecContextavcodec_open2()的声明位于libavcodec\avcodec.h&#xff0c;如下所示。 /*** Initialize the AVCodecContext to use…

统计MySQL中某数据库硬盘占用量大小

放码过来 select TABLE_NAME, concat(truncate(data_length/1024/1024,2), MB) as data_size, concat(truncate(index_length/1024/1024,2), MB) as index_size from information_schema.tables where TABLE_SCHEMA your_db_name order by data_length desc;运行结果 参考…

halcon 相似度_Halcon分类函数,shape模型

《zw版Halcon-delphi系列原创教程》 Halcon分类函数013,shape模型为方便阅读&#xff0c;在不影响说明的前提下&#xff0c;笔者对函数进行了简化&#xff1a;:: 用符号“**”&#xff0c;替换&#xff1a;“procedure”:: 用大写字母“X”&#xff0c;替换&#xff1a;“IHUnt…

用Python将文件夹打包成Zip并备份至U盘

需求概要 将maven工程打包并备份至U盘。为了简单起见&#xff0c;只需备份工程中的src文件夹和pom.xml文件即可。 放码过来 import os import zipfile import datetime import shutilnowTimeStr datetime.datetime.now().strftime("%Y%m%d%H%M") newZipFileName …

FFmpeg源代码简单分析-通用-avcodec_close()

参考链接 FFmpeg源代码简单分析&#xff1a;avcodec_close()_雷霄骅的博客-CSDN博客_avcodec_close avcodec_close() 该函数用于关闭编码器avcodec_close()函数的声明位于libavcodec\avcodec.h&#xff0c;如下所示。 ​该函数只有一个参数&#xff0c;就是需要关闭的编码器的…

redis 缓存过期默认时间_redis缓存过期机制

笔者在线上使用redis缓存的时候发现即使某些查询已经设置了无过期时间的缓存,但是查询仍然非常耗时。经过排查,发现缓存确实已经不存在,导致了缓存击穿,查询直接访问了mysql数据库。因为我们用的是公司公共的redis缓存服务器,在和运维人员交流后发现可能是redis的内存淘汰…

FFmpeg源代码简单分析-解码-打开媒体的函数avformat_open_input

参考链接 图解FFMPEG打开媒体的函数avformat_open_input_雷霄骅的博客-CSDN博客_avformat_open_input 使用FFmpeg源代码简单分析&#xff1a;avformat_open_input()_雷霄骅的博客-CSDN博客_avformat_open_input() avformat_open_input FFmpeg打开媒体的的过程开始于avformat_…

redis session java获取attribute_面试题:给我说说你能想到几种分布式session实现?...

作者&#xff1a;yanglbme 来源&#xff1a;https://github.com/doocs/advanced-java/blob/master/docs/distributed-system/distributed-session.md# 面试官心理分析面试官问了你一堆 dubbo 是怎么玩儿的&#xff0c;你会玩儿 dubbo 就可以把单块系统弄成分布式系统&#xff0…

Projection投影

解释一 Projection means choosing which columns (or expressions) the query shall return. Selection means which rows are to be returned. if the query is select a, b, c from foobar where x3;then “a, b, c” is the projection part, “where x3” the selecti…

FFmpeg源代码简单分析-解码-avformat_find_stream_info()

参考链接 FFmpeg源代码简单分析&#xff1a;avformat_find_stream_info()_雷霄骅的博客-CSDN博客_avformat_find_stream_info avformat_find_stream_info() ​该函数可以读取一部分视音频数据并且获得一些相关的信息avformat_find_stream_info()的声明位于libavformat\avform…

Tail Recursion尾递归

什么是尾递归 Tail Recursion /teɪl rɪˈkɜːrʒn/ In traditional recursion, the typical model is that you perform your recursive calls first, and then you take the return value of the recursive call and calculate the result. In this manner, you don’t g…

python递归算法案例教案_python教案

第五单元进阶程序设计(总10课时)第一节选择编程语言(1课时)一、教学目标1、了解程序设计语言和两种翻译方式&#xff1b;2、了解Python背景、功能、安装&#xff0c;熟悉Python编程环境&#xff1b;3、编程初体验。体验一个小程序从建立、输入、调试、运行、保存的全过程。掌握…

FFmpeg源代码简单分析-解码-av_read_frame()

参考链接 ffmpeg 源代码简单分析 &#xff1a; av_read_frame()_雷霄骅的博客-CSDN博客_ffmpeg frame av_read_frame() ffmpeg中的av_read_frame()的作用是读取码流中的音频若干帧或者视频一帧。例如&#xff0c;解码视频的时候&#xff0c;每解码一个视频帧&#xff0c;需要…