编码可以简单理解为将连续的图片帧转变成视频流的过程。以H264为例给出编码的代码:
int InitEncoderCodec(int width, int height) { auto enc = avcodec_find_encoder(AV_CODEC_ID_H264); encodeContext = avcodec_alloc_context3(enc); auto codec = encodeContext; codec->codec_id = enc->id; codec->time_base.num = 1; codec->time_base.den = 25; codec->gop_size = 10; codec->bit_rate = 400000; codec->pix_fmt = AV_PIX_FMT_YUV420P; codec->width = width; codec->height = height; codec->has_b_frames = 0; codec->max_b_frames = 0; AVDictionary* options = nullptr; if (!av_dict_get(options, "threads", nullptr, 0)) { av_dict_set(&options, "threads", "auto", 0); } auto hr = avcodec_open2(codec,enc,nullptr); return hr; }
稍微解释下:AV_CODEC_ID_H264是264 codec ID,如果是其他的编码器替换相应的ID. avcodec_open2返回0表示打开编码器成功,打开失败返回负值。
encode输入是一个AVFrame。注意:Frame的宽高要与codec的宽高一致。编码后的packet组成PES流。
shared_ptr<AVPacket> encode(AVFrame* frame) { int gotpacket = 0; shared_ptr<AVPacket> packet = nullptr; shared_ptr<AVPacket> pkt((AVPacket*)av_malloc(sizeof(AVPacket)), [&](AVPacket *p){av_free_packet(p);av_freep(&p);}); av_init_packet(pkt.get()); pkt->data = nullptr; pkt->size = 0; int hr = avcodec_encode_video2(encodeContext, pkt.get(), frame, &gotpacket); if(hr >= 0 && gotpacket) { packet = pkt; } return packet; }