#include <stdio.h>
#include <libavcodec/avcodec.h>
//#include <libavutil/time.h>
#include <libavformat/avformat.h>
static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
AVFormatContext *oc)
{
int ret;
ret = avcodec_send_frame(enc_ctx, frame);
if (ret < 0) {
fprintf(stderr, "Error sending a frame for encoding\n");
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_packet(enc_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error during encoding\n");
exit(1);
}
//printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
//fwrite(pkt->data, 1, pkt->size, outfile)
;
//将编码后的帧写入文件
av_interleaved_write_frame(oc, pkt);
av_packet_unref(pkt);
}
}
int main(int argc, char* argv[])
{
const char *ifile = "./test/clip.yuv";
const char *ofile = "111.ts";
int bitrate = 5000000;
int width = 1280;
int height = 720;
int fps = 30;
int ret = -1;
unsigned int read_size;
int64_t start_time;
AVCodec* codec;
AVFrame *frame;
AVPacket *pkt;
AVCodecContext *codec_ctx;
///
AVFormatContext *oc = NULL;
FILE *input_fp = fopen(ifile, "rb");
if (input_fp == NULL)
{
fprintf(stderr, "Could not to open inputfile.\n");
return -1;
}
// output_fp = fopen("./clip2.ts", "wb");
// if (!output_fp )
// {
// fprintf(stderr, "Could not open outputfile.\n");
// return -1;
// }
fseek(input_fp, 0, SEEK_END);
unsigned int infile_size = ftell(input_fp);
unsigned int frame_cnt = infile_size / (width*height*3/2);
printf("frame_cnt frame_cnt %3d \n", frame_cnt);
codec = avcodec_find_encoder_by_name("libxvid");
if (!codec) {
fprintf(stderr,"Codec not found\n");
return -1;
}
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {
fprintf(stderr,"Could not allocate video codec context\n");
return -1;
}
codec_ctx->bit_rate = bitrate;
codec_ctx->width = width;
codec_ctx->height = height;
codec_ctx->time_base = (AVRational){1, fps};
codec_ctx->framerate = (AVRational){fps, 1};
//codec_ctx->gop_size = 4;
codec_ctx->max_b_frames = 2;
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
//av_opt_set(codec_ctx->priv_data, "preset", "slow", 0);
ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {
fprintf(stderr,"Could not open codec: %s\n", av_err2str(ret));
return -1;
}
/
//2 create out context
avformat_alloc_output_context2(&oc, 0, 0, ofile);
//3 add video stream
AVStream *st = avformat_new_stream(oc, NULL);
st->id = 0;
st->codecpar->codec_tag = 0;
avcodec_parameters_from_context(st->codecpar, codec_ctx);
av_dump_format(oc, 0, ofile, 1);
//5 write mp4 head
ret = avio_open(&oc->pb, ofile, AVIO_FLAG_WRITE);
if (ret < 0)
{
fprintf(stderr," avio_open failed! \n");
getchar();
return -1;
}
ret = avformat_write_header(oc, NULL);
if (ret < 0)
{
fprintf(stderr," avformat_write_header failed! \n");
getchar();
return -1;
}
/
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr,"Could not allocate video frame\n");
return -1;
}
frame->format = codec_ctx->pix_fmt;
frame->width = codec_ctx->width;
frame->height = codec_ctx->height;
ret = av_frame_get_buffer(frame, 32);
if (ret < 0) {
fprintf(stderr, "Could not allocate the video frame data\n");
return -1;
}
pkt = av_packet_alloc();
if (!pkt) {
return -1;
}
//start_time = av_gettime_relative();
fseek(input_fp, 0, SEEK_SET);
// Loop over all frames in inputfile
int i, j;
for (i = 0; i < frame_cnt; i++)
{
// Make sure the frame data is writable
int rc = av_frame_make_writable(frame);
if (rc < 0)
{
fprintf(stderr, "av_frame_make_writable() error.\n");
return -1;
}
// Read data for Y into frame buffer
for (j = 0; j < codec_ctx->height; j++)
{
read_size = fread(&frame->data[0][0] + j * frame->linesize[0], codec_ctx->width, 1, input_fp);
if (read_size != 1) {
fprintf(stderr, "Failed to read Y. read_size=%u.\n", read_size);
return -1;
}
}
// Read data for U into frame buffer
for (j = 0; j < codec_ctx->height / 2; j++)
{
read_size = fread(&frame->data[1][0] + j * frame->linesize[1], codec_ctx->width / 2, 1, input_fp);
if (read_size != 1) {
fprintf(stderr, "Failed to read U. read_size=%u.\n", read_size);
return -1;
}
}
// Read data for V into frame buffer
for (j = 0; j < codec_ctx->height / 2; j++)
{
read_size = fread(&frame->data[2][0] + j * frame->linesize[2], codec_ctx->width / 2, 1, input_fp);
if (read_size != 1)
{
fprintf(stderr, "Failed to read V. read_size=%u.\n", read_size);
return -1;
}
}
frame->pts = i * 90000 / fps;
// Encode frame
encode(codec_ctx, frame, pkt, oc);
//print_report(0, start_time, av_gettime_relative(), i);
}
//sleep(2);
encode(codec_ctx, NULL, pkt, oc);
//print_report(0, start_time, av_gettime_relative(), frame_cnt);
//写文件尾
av_write_trailer(oc);
//关闭视频输出IO
avio_close(oc->pb);
//清理封装输出上下文
avformat_free_context(oc);
//fclose(output_fp);
fclose(input_fp);
//清理编码器上下文
avcodec_free_context(&codec_ctx);
av_frame_free(&frame);
av_packet_free(&pkt);
return 0;
}