/*
* 一笑奈何
* cn-yixiaonaihe.blog.csdn.net
*/#include <iostream>
#include <thread>
extern "C" {
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
}
using namespace std;
static double r2d(AVRational r)
{return r.den == 0 ? 0 : (double)r.num / (double)r.den;
}
void XSleep(int ms)
{//c++ 11chrono::milliseconds du(ms);this_thread::sleep_for(du);
}
int main(int argc, char *argv[])
{cout << "Test Demux FFmpeg.club" << endl;const char *url = "test.rgb";const char *outfile = "test.mov";//初始化封装库av_register_all();//初始化网络库 (可以打开rtsp rtmp http 协议的流媒体视频)avformat_network_init();//注册解码器avcodec_register_all();FILE *fp = fopen(url,"rb");int width = 1920;int height = 1080;int fps = 25;static int i = 0;char errorbuf[1024];if (!fp){cout << "open FILE failed!" << endl;fclose(fp);return -1;}AVCodec *codec=avcodec_find_encoder(AV_CODEC_ID_H264);if (!codec){cout << "avcodec_find_encoder No" << endl;return -1;}AVCodecContext *c = avcodec_alloc_context3(codec);if (!c){cout << "avcodec_alloc_context3 No" << endl;return -1;}c->bit_rate = 400000000;c->width = width;c->height = height;c->time_base = { 1,fps };c->framerate = { fps,1 };c->gop_size = 50;c->max_b_frames = 0;c->pix_fmt = AV_PIX_FMT_YUV420P;c->codec_id = AV_CODEC_ID_H264;c->thread_count = 8;//全局编码c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;int ret = avcodec_open2(c, codec, 0);if (ret < 0){cout << "avcodec_open2 No" << endl;return -1;}cout << "avcodec_open2 OK" << endl;//2 create out contextAVFormatContext *oc = nullptr;avformat_alloc_output_context2(&oc, 0, 0, outfile);//3 add video streamAVStream *st = avformat_new_stream(oc, NULL);//st->codec = c;st->id = 0;st->codecpar->codec_tag = 0;avcodec_parameters_from_context(st->codecpar,c);cout << "========================" << endl;av_dump_format(oc, 0, outfile, 1);cout << "========================" << endl;//4 rgb to yuvSwsContext *ctx = NULL;ctx = sws_getCachedContext(ctx,width, height, AV_PIX_FMT_BGRA,width, height, AV_PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);//输入的空间unsigned char *rgb = new unsigned char[width * height * 4];//输出的空间AVFrame *yuv = av_frame_alloc();yuv->format = AV_PIX_FMT_YUV420P;yuv->width = width;yuv->height = height;//分配空间ret=av_frame_get_buffer(yuv, 32);if (ret < 0){cout << "av_frame_get_buffer No" << endl;return -1;}//5 wirte mp4 head//写入文件头信息ret = avio_open(&oc->pb, outfile, AVIO_FLAG_WRITE);//打开输出文件IOif (ret < 0){cout << "avio_open failed" << endl;getchar();return -1;}ret = avformat_write_header(oc, NULL);if (ret < 0){cout << "avformat_write_header failed" << endl;getchar();}int p = 0;for (;;){int len = fread(rgb, 1, width * height * 4, fp);if (len <= 0)break;uint8_t *indata[AV_NUM_DATA_POINTERS] = { 0 };indata[0] = rgb;int inlinesize[AV_NUM_DATA_POINTERS] = { 0 };inlinesize[0] = width * 4;//*4字节数int h=sws_scale(ctx, indata, inlinesize, 0, height,yuv->data,yuv->linesize);if (h <= 0)break;//6 encode frameyuv->pts = p;p = p + 3600;//yuv->pict_type = AV_PICTURE_TYPE_I;ret=avcodec_send_frame(c, yuv);if (ret != 0){continue;}AVPacket pkt;av_init_packet(&pkt);//一次发送可能多次接收ret = avcodec_receive_packet(c, &pkt);if (ret != 0){av_strerror(ret, errorbuf, sizeof(errorbuf));cout << "avcodec_receive_packet NO ->" << errorbuf << " "<<ret<<endl;cout << " Number :" << i << " "<<ret<<endl;i++;continue;}//av_write_frame(oc, &pkt);//av_packet_unref(&pkt);av_interleaved_write_frame(oc, &pkt);cout << "<" << pkt.size << ">";}//写入视频索引尾部信息av_write_trailer(oc);//主动关闭后才可以把缓冲区的内容写到文件avio_close(oc->pb);//清理封装输出上下文avformat_free_context(oc);//关闭编码器avcodec_close(c);//清理编码器上下文avcodec_free_context(&c);//清理视频重采样上下文sws_freeContext(ctx);delete rgb;fclose(fp);cout << "==================end===============" << endl;return 0;
}