FFmpeg Encode(编码)

【FFMPEG】encoder深入分析 深入分析encoder过程中数据流转过程 阅读详情
AI摘要

本文介绍如何使用FFmpeg库进行音频和视频的编码处理。主要内容包括初始化编码器、处理原始音频和视频帧、生成编码后的数据包,并将其封装到输出文件中。通过两个具体的示例程序,分别展示了音频AAC和视频H.264的编码过程。

首发地址,会更错

本文来自官方例子doc/examples/encode_audio.c 和 doc/examples/encode_video.c。

FFmpeg编码流程

流程

其中,AVFormatContext、AVPacket等重要的结构体请看:FFmpeg重要结构体(转自雷神) 。

官方例子【Audio】

/**
 * @author 秦城季
 * @email xhunmon@126.com
 * @Blog https://qincji.gitee.io
 * @date 2021/01/07
 * description: 来自官方例子:doc/examples/encode_audio.c
 * 主要思路:
 * 1、初始化编码器信息
 * 2、从文件(或者生成)读取裸流数据到每个AVFrame中
 * 3、把每个AVFrame通过编码器生成编码后数据的AVPacket
 * 4、使用AVFormatContext封装到文件中进行输出
 *
 * <br>
 */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

extern "C"{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>

#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
}

/* check that a given sample format is supported by the encoder */
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{
    const enum AVSampleFormat *p = codec->sample_fmts;

    while (*p != AV_SAMPLE_FMT_NONE) {
        if (*p == sample_fmt)
            return 1;
        p++;
    }
    return 0;
}

/* just pick the highest supported samplerate */
static int select_sample_rate(const AVCodec *codec)
{
    const int *p;
    int best_samplerate = 0;

    if (!codec->supported_samplerates)
        return 44100;

    p = codec->supported_samplerates;
    while (*p) {
        if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
            best_samplerate = *p;
        p++;
    }
    return best_samplerate;
}

/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec *codec)
{
    const uint64_t *p;
    uint64_t best_ch_layout = 0;
    int best_nb_channels   = 0;

    if (!codec->channel_layouts)
        return AV_CH_LAYOUT_STEREO;

    p = codec->channel_layouts;
    while (*p) {
        int nb_channels = av_get_channel_layout_nb_channels(*p);

        if (nb_channels > best_nb_channels) {
            best_ch_layout    = *p;
            best_nb_channels = nb_channels;
        }
        p++;
    }
    return best_ch_layout;
}

static int f_index = 0;

static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt,
                   FILE *output,AVFormatContext *ofmt_ctx)
{
    int ret;

    /* send the frame for encoding */
    ret = avcodec_send_frame(ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending the frame to the encoder\n");
        exit(1);
    }

    /* read all the available output packets (in general there may be any
     * number of them */
    while (ret >= 0) {
        ret = avcodec_receive_packet(ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error encoding audio frame\n");
            exit(1);
        }

        //(封装——数据写入)
        //Convert PTS/DTS
        pkt->pts = f_index *100;
        pkt->dts = f_index *100;
        pkt->pos = -1;
        pkt->stream_index = 0;

        printf("Write 1 Packet. size:%5d\tpts:%lld\n", pkt->size, pkt->pts);
        //Write
        if (av_interleaved_write_frame(ofmt_ctx, pkt) < 0) {
            printf("Error muxing packet\n");
            break;
        }
        f_index++;

        av_packet_unref(pkt);
    }
}

int main(int argc, char **argv)
{
    const char *outFilename, *inFilename;
    const AVCodec *codec;
    AVCodecContext *c= NULL;
    AVFrame *frame;
    AVPacket *pkt;
    int i, j, k, ret;
    FILE *outFile, *inFile;

    outFilename = "output/Kobe.aac";
    inFilename = "source/Kobe.pcm";

    remove(outFilename);

    //获取 AVCodec
    codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
    if (!codec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }
    //获取AVCodecContext
    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate audio codec context\n");
        exit(1);
    }

    //设置编码参数:
    c->bit_rate = 34000;
    c->sample_fmt = AV_SAMPLE_FMT_FLTP;

    //音频:检测当前编码器是否支持采样格式
    if (!check_sample_fmt(codec, c->sample_fmt)) {
        fprintf(stderr, "Encoder does not support sample format %s",
                av_get_sample_fmt_name(c->sample_fmt));
        exit(1);
    }

    /* 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);


    //初始化AVCodecContext
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }

    inFile = fopen(inFilename, "rb");
    if (!inFile) {
        fprintf(stderr, "Could not open %s\n", inFilename);
        exit(1);
    }

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

    /* packet for holding encoded output */
    pkt = av_packet_alloc();
    if (!pkt) {
        fprintf(stderr, "could not allocate the packet\n");
        exit(1);
    }

    /* frame containing input raw audio */
    frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr, "Could not allocate audio frame\n");
        exit(1);
    }

    //设置 AVFrame的参数
    frame->nb_samples     = c->frame_size;
    frame->format         = c->sample_fmt;
    frame->channel_layout = c->channel_layout;

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


    /***************************************************************************/
    /*****************      以下是对PCM编码后的AVPacket数据再进行封装成AAC      ******/
    /***************************************************************************/
    //(封装——初始化)
    //Output
    AVFormatContext *ofmt_ctx = NULL;
    AVOutputFormat *ofmt = NULL;
    avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, outFilename);
    if (!ofmt_ctx) {
        printf("Could not create output context\n");
        return -1;
    }
    ofmt = ofmt_ctx->oformat;
    AVStream *out_stream = avformat_new_stream(ofmt_ctx, codec);
    //Copy the settings of AVCodecContext
    if (avcodec_copy_context(out_stream->codec, c) < 0) {
        printf("Failed to copy context from input to output stream codec context\n");
        return -1;
    }
    out_stream->codec->codec_tag = 0;
    if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

    /* open the output file, if needed */
    if (!(ofmt->flags & AVFMT_NOFILE)) {
        if (avio_open(&ofmt_ctx->pb, outFilename, AVIO_FLAG_WRITE)) {
            fprintf(stderr, "Could not open '%s': %s\n", outFilename,
                    av_err2str(ret));
            return -1;
        }
    }

    //Write file header //(封装——文件头)
    if (avformat_write_header(ofmt_ctx, NULL) < 0) {
        fprintf(stderr, "Error occurred when opening output file: %s\n",
                av_err2str(ret));
        return -1;
    }



    //每个通道占的字节数
    int data_size = av_get_bytes_per_sample(c->sample_fmt);

    while (!feof(inFile)){
        /* make sure the frame is writable -- makes a copy if the encoder
         * kept a reference internally */
        ret = av_frame_make_writable(frame);

        if (ret < 0)
            exit(1);

        for (i = 0; i < c->frame_size; i++)
            for (j = 0; j < c->channels; j++)
                fread(frame->data[j] + data_size*i, 1, data_size, inFile);
        encode(c, frame, pkt, outFile,ofmt_ctx);
    }

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

    printf("Write file trailer.\n");

    //Write file trailer//(封装——文件尾)
    av_write_trailer(ofmt_ctx);

    fclose(outFile);

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

    return 0;
}

官方例子【Video】

改动的本例子,使用x264库进行解码。所以需要集成x264库,请参考 编译ffmpeg4.2.2 。

我这里使用在MacOS上面跑的例子,以下是我本例编译ffmpeg的脚本:

#!/bin/bash

make clean

function build_x264() {
  cd libx264
  ./configure \
    --prefix=${X264_LIBS} \
    --disable-static \
    --enable-shared || exit 0
  make clean
  make install
}

function build_macosx() {
   cd ..
  ./configure \
    --prefix=$PREFIX \
    --disable-programs \
    --enable-ffmpeg \
    --target-os=darwin \
    --disable-static \
    --enable-shared \
    --extra-cflags="-fPIC" \
    --ln_s="ln -s" \
    --pkg-config=$(which pkg-config) \
    --enable-gpl \
    --extra-cflags="-I${X264_LIBS}/include" \
    --extra-ldflags="-L${X264_LIBS}/lib" \
    --enable-libx264 || exit 0

  make clean
  make install
}

PREFIX=$(pwd)/macox
X264_LIBS=$(pwd)/libx264/libouput

build_x264
build_macosx

编译完成后,会在项目根目录上传ffmpeg工具,可以通过以下操作查看是否正常集成:

./ffmpeg -re -i input.mp4 -vcodec libx264 -an output.mp4

编码例子:

/**
 * @author 秦城季
 * @email xhunmon@126.com
 * @Blog https://qincji.gitee.io
 * @date 2021/01/07
 * description: 来自官方例子:doc/examples/encode_video.c
 * 主要思路:
 * 1、初始化编码器信息
 * 2、从文件(或者生成)读取裸流数据到每个AVFrame中
 * 3、把每个AVFrame通过编码器生成编码后数据的AVPacket
 * 4、使用AVFormatContext封装到文件中进行输出
 *
 * <br>
 */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>

#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>

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

static int f_index = 0;

static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt,
                   FILE *output, AVFormatContext *ofmt_ctx) {
    int ret;
    //注意:需要在送去编码器前指定 pts 
    frame->pts = f_index++;

    /* send the frame for encoding */
    ret = avcodec_send_frame(ctx, frame);
    if (ret < 0) {
        fprintf(stderr, "Error sending the frame to the encoder\n");
        exit(1);
    }

    /* read all the available output packets (in general there may be any
     * number of them */
    while (ret >= 0) {
        ret = avcodec_receive_packet(ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
            return;
        else if (ret < 0) {
            fprintf(stderr, "Error encoding audio frame\n");
            exit(1);
        }

        //(封装——数据写入)
        pkt->stream_index = 0;

        printf("Write 1 Packet. size:%5d\tpts:%lld\n", pkt->size, pkt->pts);
        //Write
        if (av_interleaved_write_frame(ofmt_ctx, pkt) < 0) {
            printf("Error muxing packet\n");
            break;
        }

        av_packet_unref(pkt);
    }
}

int main(int argc, char **argv) {
    const char *outFilename, *inFilename;
    const AVCodec *codec;
    AVCodecContext *c = NULL;
    AVFrame *frame;
    AVPacket *pkt;
    int ret;
    FILE *outFile, *inFile;

    outFilename = "output/Kobe.h264";
    inFilename = "source/Kobe.yuv";

    remove(outFilename);

    //获取 AVCodec
    codec = avcodec_find_encoder(AV_CODEC_ID_H264);
    if (!codec) {
        fprintf(stderr, "Codec not found\n");
        exit(1);
    }
    //获取AVCodecContext
    c = avcodec_alloc_context3(codec);
    if (!c) {
        fprintf(stderr, "Could not allocate audio codec context\n");
        exit(1);
    }

    //设置编码参数:Stream #0:0: Video: h264 (Main), yuv420p(progressive), 384x216 [SAR 1:1 DAR 16:9], 15 fps, 15 tbr, 1200k tbn, 30 tbc
    /* put sample parameters */
    c->bit_rate = 120000;
    /* resolution must be a multiple of two */
    c->width = 384;
    c->height = 216;
    /* frames per second */
    c->time_base = (AVRational) {1, 15};
    c->framerate = (AVRational) {15, 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);


    //初始化AVCodecContext
    if (avcodec_open2(c, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec\n");
        exit(1);
    }

    inFile = fopen(inFilename, "rb");
    if (!inFile) {
        fprintf(stderr, "Could not open %s\n", inFilename);
        exit(1);
    }

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

    /* packet for holding encoded output */
    pkt = av_packet_alloc();
    if (!pkt) {
        fprintf(stderr, "could not allocate the packet\n");
        exit(1);
    }

    /* frame containing input raw audio */
    frame = av_frame_alloc();
    if (!frame) {
        fprintf(stderr, "Could not allocate audio frame\n");
        exit(1);
    }

    //设置 AVFrame的参数
    frame->format = c->pix_fmt;
    frame->width = c->width;
    frame->height = c->height;

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


    /***************************************************************************/
    /*****************      以下是对PCM编码后的AVPacket数据再进行封装成AAC      ******/
    /***************************************************************************/
    //(封装——初始化)
    //Output
    AVFormatContext *ofmt_ctx = NULL;
    AVOutputFormat *ofmt = NULL;
    avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, outFilename);
    if (!ofmt_ctx) {
        printf("Could not create output context\n");
        return -1;
    }
    ofmt = ofmt_ctx->oformat;
    AVStream *out_stream = avformat_new_stream(ofmt_ctx, codec);
    //Copy the settings of AVCodecContext
    if (avcodec_copy_context(out_stream->codec, c) < 0) {
        printf("Failed to copy context from input to output stream codec context\n");
        return -1;
    }
    out_stream->codec->codec_tag = 0;
    if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
        out_stream->codec->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;

    /* open the output file, if needed */
    if (!(ofmt->flags & AVFMT_NOFILE)) {
        if (avio_open(&ofmt_ctx->pb, outFilename, AVIO_FLAG_WRITE)) {
            fprintf(stderr, "Could not open '%s': %s\n", outFilename,
                    av_err2str(ret));
            return -1;
        }
    }

    //Write file header //(封装——文件头)
    if (avformat_write_header(ofmt_ctx, NULL) < 0) {
        fprintf(stderr, "Error occurred when opening output file: %s\n",
                av_err2str(ret));
        return -1;
    }


    while (!feof(inFile)) {
        /* make sure the frame is writable -- makes a copy if the encoder
         * kept a reference internally */
        ret = av_frame_make_writable(frame);

        if (ret < 0)
            exit(1);

        fread(frame->data[0], 1, frame->height * frame->width, inFile); //Y
        fread(frame->data[1], 1, frame->height * frame->width/4, inFile); //U
        fread(frame->data[2], 1, frame->height * frame->width/4, inFile); //V
        encode(c, frame, pkt, outFile, ofmt_ctx);
    }

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

    printf("Write file trailer.\n");

    //Write file trailer//(封装——文件尾)
    av_write_trailer(ofmt_ctx);

    fclose(outFile);

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

    return 0;
}


ffmpeg源码简析(五)编码——avformat_alloc_output_context2(),avcodec_encode_video2() 1.avformat_alloc_output_context2()在基于FFmpeg的视音频编码器程序中,该函数通常是第一个调用的函数(除了组件注册函数av_register_all())。avformat_alloc_output_context2()函数可以初始化一个用于输出的AVFormatContext结构体。它的声明位于libavformat\avformat.h,如下所示。int av 阅读详情

相关推荐

FFmpeg源代码简单分析 avcodec encode video

FFmpeg源代码简单分析 avcodec encode video

hffgjh的博客 413

FFMPEG Demo分析之encode_video.c

前言 本系列文章 FFMPEG Demo分析之muxing.c FFMPEG Demo分析之demuxing_decoding.c FFMPEG Demo分析之decode_video.c 本篇文章来介绍一下单独使用libavcodec库进行编码视频文件。编码音频和编码视频的步骤其实都差不多。先来简单介绍下编码的步骤。步骤如下: 找到编码器->分配编码器上下文->给编码器上下文赋值一些必要的编码参数->打开编码器->分配AVPacket和AVFrame->给AVFrame赋值一

刘信的博客 791

【FFmpeg编程进阶】(12)FLV 编码函数 ff_mpv_encode_picture() 代码分析 --- 待更新

【FFmpeg编程进阶】(11)FLV 编码函数 ff_mpv_encode_picture 代码分析 --- 待更新一、ff_mpv_encode_picture() 本文接着:《【FFmpeg编程进阶】(11)avcodec_open2() 函数代码分析 - 打开Codec解码器》 本文主要来分析下,编码的代码流程,以 FLV 为例,它的编码函数为 ff_mpv_encode_picture() # libavcodec\flvenc.c AVCodec ff_flv_encoder = {

|~~~热爱生活、努力学习的小伙汁~~~| 1084

ffmpeg代码实现自定义encoder

1、概述 本文主要讲述如何用ffmpeg代码实现自己的encoder。 2、代码 [cpp] view plain copy /*   *本程序主要实现一个自己的encoder并加入到encoder链中去,供api调用  *作者:缪国凯(MK)   *821486004@qq.com   *2015-6-4   */       #

华的专栏 1247

【FFmpeg编程进阶】(15)FLV 编码器Codec初始化 ff_mpv_encode_init() 代码分析 -- 待更新

【FFmpeg编程进阶】(15)FLV 编码器Codec初始化 ff_mpv_encode_init 代码分析 一、ff_mpv_encode_init() 在前面分析《【FFmpeg编程进阶】(11)avcodec_open2() 函数代码分析 - 打开Codec解码器》时, 我们涉及到了Codec 编码器初始化,由于代码比较长,我们再分一章来分析。 主要目的,还是以 FLV 编码器为例 ,来看下编码器初始化主要做了啥 先记录下TODO LIST,后面再更新。 # libavcodec\flvenc.c

|~~~热爱生活、努力学习的小伙汁~~~| 1120

ffmpeg官方demo——encode.c学习(已修改已加注释)

初次学习ffmpeg官方demo,对encode.c代码进行了修改并添加了注释 代码可运行在QT环境中,也可以单独编码运行main.cpp 可搭配个人博客 【ffmpeg初次学习(仅针对编码)】搭配食用

FFmpeg旧编码接口avcodec_encode_video()解析与迁移

视频编码是多媒体开发的核心环节,FFmpeg作为最广泛使用的开源音视频库,其编码接口经历了多轮演进。早期版本通过avcodec_encode_video()这类同步式接口完成单帧编码,但随着H.264/H.265等现代编码器引入B帧缓冲和延迟输出,一次调用一进一出的模型暴露出局限性,开发者常需处理got_packet标志和flush操作。理解这些底层原理,不仅有助于维护遗留项目、迁移旧代码,也能更清晰地把握AVPacket、pts/dts等核心概念。新接口avcodec_send_frame/avcodec

weixin_31286719的博客 236

最简单的基于FFMPEG的视频编码器(YUV编码为HEVC H 265 )

FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手。因此特地分离出了一个简单的视频编码器供学习之用。 此前做过一个YUV420P像素数据编码为H.264码流的例子。对这个例子进行了升级。升级后编码器实现了YUV420P像素数据编码为H.265码流。 尽管该视频编码器的代码十分简单,但是几乎包含了使用FFMPEG编码一个视频所有必备的API。十分适合FFmpeg的初学者。 工程基于VC2010。 使用了2014.9.16编译的FFmpeg类库。">FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手。因此特地分离出了一个简单的视频编码器供学习之用。 此前做过一个YUV420P像素数据编码为H.264码流的例子。对这个例子进行了升级。? [更多]

ffmpeg avcodec_encode_video2 前面10多帧不能实时编码

ffmpeg avcodec_encode_video2 前面10多帧不能实时编码,查找原因!版本v1.2.1

smilestone322的专栏 5133

十一种室内定位传感器方案汇总介绍与对比(机器人、物联网领域)

室内定位传感器方案汇总 目录 室内定位传感器方案汇总 1、定位方案概述 1.1、内定位系统有最基本的5种算法: 1.2、常用的室内定位技术主要包括以下几种: 1.3、定位理论 1.4、不同的定位方案对比 2、各种定位方案详细介绍 2.1、单线激光定位 2.2、多线激光定位: 2.3、视觉定位: 2.4、基于射频识别(RFID)技术室内定位 2.4.1、RFID标签(不涉及...

JK-Cool的博客 3万+

华大HC32F460从零到200MHz:手把手教你配置时钟系统(附避坑指南)

本文详细解析了华大HC32F460 MCU的时钟系统配置,从启动过程、时钟树分析到实战配置200MHz系统时钟。文章手把手指导开发者如何正确配置外部晶振、MPLL锁相环及总线分频,并提供了硬件检查、代码解读及常见问题排查的避坑指南,帮助用户从零构建稳定可靠的高性能时钟环境。

net55的博客 294

FFmpeg源代码简单分析-编码-avcodec_encode_video()已被send_frame 和 receive_packet替代

FFmpeg源代码简单分析-编码-avcodec_encode_video()已被send_frame 和 receive_packet替代

CHYabc123456hh的博客 1180

手把手教你用TJA1145A实现CAN节点智能唤醒(含数据帧过滤技巧)

本文详细介绍了如何使用TJA1145A收发器实现CAN节点的智能唤醒功能,包括数据帧过滤技巧和超低功耗设计。通过硬件级帧过滤和双条件唤醒机制,TJA1145A在保持微安级休眠电流的同时,能对特定报文做出毫秒级响应,显著提升电池供电设备的续航能力。

weixin_28721917的博客 249

FFmpeg从入门到牛掰(四):音频编码(encode )讲解

转载请注明出处:https://blog.youkuaiyun.com/impingo 项目地址:https://github.com/im-pingo/pingos 音频编码讲解流程描述函数接口音频编码代码示例 流程描述 上篇文章【FFmpeg从入门到牛掰(三):音频解码(decode)讲解】介绍了音频解码的过程,所谓解码就是将AAC、mp3这类音频压缩算法处理过的数据还原成pcm数据的过程,那么音频编码就...

impingo的博客 3003

数字IC后端设计实战:从floorplan到powerplan的优化策略

本文深入探讨了数字IC后端设计中从Floorplan到Powerplan的核心优化策略。文章强调了Floorplan作为布局基础的重要性,并详细解析了Powerplan规划,特别是针对低功耗设计中MTCMOS的应用与IR Drop分析。通过实战经验分享,提供了从模块摆放到电源网络构建、再到IR Drop问题层层递进的解决方案,旨在帮助后端工程师构建稳健高效的芯片物理设计。

weixin_28338005的博客 347

WPS Office 2026免费安装指南:AI办公与安全使用全解析

办公软件作为数字化办公的核心工具,其基本原理是通过文档处理、数据计算和演示展示等功能模块满足用户日常办公需求。随着人工智能技术的发展,现代办公软件逐步集成AI能力,通过自然语言处理和数据分析算法提升工作效率。在技术价值层面,优秀的办公软件不仅需要保持格式兼容性和跨平台同步能力,更要注重用户数据安全防护。从应用场景来看,无论是个人文档编辑、企业报表分析还是团队协作演示,办公软件都发挥着关键作用。WPS Office 2026作为国产办公软件代表,深度融合AI助手功能,支持智能写作和数据分析,同时通过官方免费策

weixin_30599769的博客 708

推荐开源项目:FFmpeg-X264-Encode-for-iOS - 实时视频流编码神器

推荐开源项目:FFmpeg-X264-Encode-for-iOS - 实时视频流编码神器 去发现同类优质开源项目:https://gitcode.com/ 1、项目介绍 FFmpeg-X264-Encode-for-iOS 是一个专为 iOS 设备设计的开源项目,它巧妙地集成了 FFmpeg 和 x264 库,使开发者能够轻松地将 iOS 摄像头捕获的实时视频流编码为高效的 h264 格式文件。...

gitblog_00079的博客 525

GPU 资源池化云平台解决方案​

定义与特点Kubernetes是一个开源的容器编排和管理平台,通过提供自动化和声明式的方式来部署、扩展、维护和运行应用程序。它支持跨多个主机和集群部署容器,确保应用程序的高可用性和可扩展性。Kubernetes提供了丰富的功能和插件,允许用户根据自己的需求进行定制和扩展。架构与组件控制平面(Control Plane):负责集群的决策(如调度)和集群状态的检测与响应。

ZhangJiqun&191cm&85kg 1161

2023-04-09:使用 Golang 重写的 ffmpeg 示例encode_video.c,实现视频编码并将编码后的数据封装为容器格式,最终写入输出文件。

需要注意的是,在实际应用中,还需要根据具体需求进行相应的配置和优化,例如设置 GOP 大小、调整编码速度等参数,以提高视频质量和编码效率。本文介绍的是使用 Golang 重写的 ffmpeg 示例代码 encode_video.c,该示例代码实现了将视频编码并封装为容器格式,并最终写入输出文件的功能。2023-04-09:使用 Golang 重写的 ffmpeg 示例encode_video.c,实现视频编码并将编码后的数据封装为容器格式,最终写入输出文件。b. 发送视频帧到编码器,得到编码后的数据包。

福大大架构师每日一题 1万+

RK3568笔记九十四:基于QT的YOLOV5目标检测

基于RK3568平台的实时目标检测应用,使用YOLOv5模型和RKNN推理引擎实现摄像头实时目标检测,并通过Qt界面显示检测结果。主要功能实时摄像头目标检测:从摄像头获取视频流,使用YOLOv5模型进行目标检测RKNN推理加速:利用RK3568内置的NPU进行模型推理加速图形界面显示:使用Qt框架构建用户界面,实时显示检测结果RGA图像处理:使用Rockchip Graphic Accelerator进行图像缩放处理。

522

openlayers6/7 行政区划裁剪 只显示某个区域 示例为天地图

openlayers6/7 行政区划裁剪 只显示某个区域 示例为天地图。

qq_36287830的博客 3101

FFmpeg编码API迁移:从avcodec_encode_video到send_frame/receive_packet的实践

视频编码是多媒体开发中的核心环节,FFmpeg 作为行业标准工具,通过 AVFrame 与 AVPacket 分别承载原始图像与压缩码流。早期编码接口 avcodec_encode_video() 采用“用户提供缓冲区+一次性调用”的设计,但面对 B 帧延迟、缓冲区大小不可预知等场景,容易引发内存越界与丢帧。新版推荐 avcodec_send_frame() 与 avcodec_receive_packet() 组合,以“投递-取包”异步模型明确状态机,配合 EAGAIN/EOF 返回值管理编码节奏,同时由

weixin_42521558的博客 240

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构。

在该示例程序中,我们需要手动设置 FFmpeg 库的路径,以便正确加载库文件。2023-04-06:拥抱Golang,优化FFmpeg音频编码器,探究encode_audio.c的内部结构。2.定义一些变量,包括输出文件名、音频编解码器、音频编解码上下文、音频帧、音频数据包等;4.配置音频编解码参数,设置音频采样率、通道数、位率等;7.开始编码过程,并将编码后的音频数据写入输出文件中。2.将音频 PCM 数据填充到音频帧中;4.从编解码器中读取编码后的音频数据包;5.将编码后的音频数据包写入输出文件中。

福大大架构师每日一题 2万+

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Subtitle Edit 视频重编码(Re-encode Video)功能全解析:用 FFmpeg 为字幕处理优化视频

Subtitle Edit 的 **Video → More → Re-encode video for better subtitling...** 功能,允许你借助 FFmpeg 将当前视频以不同的帧率、分辨率或容器格式重新编码输出,从而让字幕编辑流程更流畅、视频兼容性更强。本文以官方文档 [re-encode-video.md](https://link.gitcode.com/i/26c8

gitblog_01105的博客 148

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

ffmpeg---旧函数avcodec_encode_video2要延迟几帧才能got_packet-----设置参数av_opt_set

ffmpeg 编码延迟问题(编码后avcodec_encode_video2要延迟几帧才能got_packet) // gcc temp.c -o 2 -I/root/ffmpeg/include/ -L/root/ffmpeg/lib -lavcodec -lavformat -lavdevice -lavutil -lswscale -lswresample //没有包含x264库 //...

qq_42024067的博客 1298
上一篇: FFmpeg Decode(解码)
下一篇: FFmpeg 简单实现转码
秦城季
博客等级 码龄10年 46粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值