Skip to content

Instantly share code, notes, and snippets.

@vaptu
Created November 28, 2018 10:06
Show Gist options
  • Save vaptu/5ea12f86f1f229cec5186637c960713b to your computer and use it in GitHub Desktop.
Save vaptu/5ea12f86f1f229cec5186637c960713b to your computer and use it in GitHub Desktop.
#include <iostream>
using namespace std;
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
}
const char *in_filename = "开场动画.mov";
const char *out_mp4 = "output.mp4";
int main() {
int ret = 0;
FILE *fp_in = nullptr;
FILE *fp_out = nullptr;
AVFormatContext *pFormatCtx = nullptr;
avcodec_register_all();
ret = avformat_open_input(&pFormatCtx, in_filename, nullptr, nullptr);
if (ret < 0) {
cerr << "Cannot open file:" << av_err2str(ret) << endl;
return 1;
}
if (avformat_find_stream_info(pFormatCtx, nullptr) < 0) {
cerr << "Canot get file info" << endl;
return 1;
}
int stream_index = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
stream_index = i;
break;
}
}
if (stream_index == -1) {
cerr << "Cannot find video stream" << endl;
return 1;
}
AVCodecContext *pCodecCtx = pFormatCtx->streams[stream_index]->codec;
AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == nullptr) {
cerr << "Cannot find decoder" << pCodecCtx->codec_id << endl;
return 1;
}
if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0) {
cerr << "Cannot open decoder" << pCodecCtx->codec_id << endl;
return 1;
}
cout << "File format: " << pFormatCtx->iformat->name << endl;
cout << "File duration: " << pFormatCtx->duration << endl;
cout << "File width and height: " << pCodecCtx->width << "-" << pCodecCtx->height << endl;
cout << "Decoder name: " << pCodec->long_name << endl;
AVFrame *pFrame = av_frame_alloc();
if (!pFrame) {
cerr << "Cannot alloc frame" << endl;
return 1;
}
AVPacket *packet = av_packet_alloc();
av_init_packet(packet);
AVFormatContext *pEncodeFormatCtx = avformat_alloc_context();
AVOutputFormat *fmt = av_guess_format(nullptr, out_mp4, nullptr);
pEncodeFormatCtx->oformat = fmt;
cout << "Encoder name: " << fmt->long_name << endl;
ret = avio_open2(&pEncodeFormatCtx->pb, out_mp4, AVIO_FLAG_READ_WRITE, nullptr, nullptr);
if (ret < 0) {
cerr << "Cannot avio_open2: " << av_err2str(ret) << endl;
return 1;
}
AVStream *video_st = avformat_new_stream(pEncodeFormatCtx, 0);
if (video_st == nullptr) {
return 1;
}
video_st->time_base.num = 1;
video_st->time_base.den = 25;
AVCodecContext *pEncodeCodecCtx = video_st->codec;
pEncodeCodecCtx->codec_id = fmt->video_codec;
pEncodeCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pEncodeCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pEncodeCodecCtx->width = 1280;
pEncodeCodecCtx->height = 720;
pEncodeCodecCtx->time_base.num = 1;
pEncodeCodecCtx->time_base.den = 25;
pEncodeCodecCtx->bit_rate = 400000;
pEncodeCodecCtx->gop_size = 250;
pEncodeCodecCtx->qmin = 10;
pEncodeCodecCtx->qmax = 51;
pEncodeCodecCtx->max_b_frames = 3;
av_dump_format(pEncodeFormatCtx, 0, out_mp4, 1);
AVCodec *pEncodeCodec = avcodec_find_encoder(pEncodeCodecCtx->codec_id);
if (!pEncodeCodec) {
cerr << "Cannot find encoder " << endl;
return 1;
}
ret = avcodec_open2(pEncodeCodecCtx, pEncodeCodec, nullptr);
if (ret < 0) {
cerr << "Cannot avcodec_open2: " << av_err2str(ret) << endl;
return 1;
}
avformat_write_header(pEncodeFormatCtx, nullptr);
AVPacket pkt;
av_init_packet(&pkt);
int y_size = pEncodeCodecCtx->width * pEncodeCodecCtx->height * 3;
av_new_packet(&pkt, y_size * 3);
while (ret = av_read_frame(pFormatCtx, packet) >= 0) {
ret = avcodec_send_packet(pCodecCtx, packet);
if (ret < 0) {
cerr << "Decode failed: " << ret << av_err2str(ret) << endl;
return 1;
}
while (ret >= 0) {
ret = avcodec_receive_frame(pCodecCtx, pFrame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
cerr << "Decode receive failed: " << av_err2str(ret) << endl;
return 1;
}
cout << "frame_number:" << pCodecCtx->frame_number << " width: " << pFrame->width << " height: "
<< pFrame->height << endl;
ret = avcodec_send_frame(pEncodeCodecCtx, pFrame);
avcodec_receive_packet(pEncodeCodecCtx, &pkt);
pkt.stream_index = stream_index;
av_write_frame(pEncodeFormatCtx, &pkt);
}
}
av_write_trailer(pEncodeFormatCtx);
if (ret < 0) {
cerr << av_err2str(ret) << endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment