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.pswp.cn/news/445976.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/445976.shtml
英文地址,請注明出處:http://en.pswp.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;需要…