Created
December 16, 2019 19:42
-
-
Save Dimanaux/3fe1402273b227898eb273bfefdbe249 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
void init_encode_context(AVCodecContext* encode_context) { | |
ctxEncode = avcodec_alloc_context(); | |
ctxEncode->coder_type = 0; // coder = 1 | |
ctxEncode->flags |=CODEC_FLAG_LOOP_FILTER; // flags=+loop | |
ctxEncode->me_cmp |= 1; // cmp=+chroma, where CHROMA = 1 | |
ctxEncode->partitions |= X264_PART_I8X8+X264_PART_I4X4 + X264_PART_P8X8 + X264_PART_B8X8; // partitions=+parti8x8+parti4x4+partp8x8+partb8x8 | |
ctxEncode->me_method = ME_HEX; // me_method=hex | |
ctxEncode->me_subpel_quality = 0; // subq=7 | |
ctxEncode->me_range = 16; // me_range=16 | |
ctxEncode->gop_size = 30 * 3; // g=250 | |
ctxEncode->keyint_min = 30; // keyint_min=25 | |
ctxEncode->scenechange_threshold = 40; // sc_threshold=40 | |
ctxEncode->i_quant_factor = 0.71; // i_qfactor=0.71 | |
ctxEncode->b_frame_strategy = 1; // b_strategy=1 | |
ctxEncode->qcompress = 0.6; // qcomp=0.6 | |
ctxEncode->qmin = 0; // qmin=10 | |
ctxEncode->qmax = 69; // qmax=51 | |
ctxEncode->max_qdiff = 4; // qdiff=4 | |
ctxEncode->max_b_frames = 3; // bf=3 | |
ctxEncode->refs = 3; // refs=3 | |
ctxEncode->directpred = 1; // directpred=1 | |
ctxEncode->trellis = 1; // trellis=1 | |
ctxEncode->flags2 |= CODEC_FLAG2_FASTPSKIP; // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip | |
ctxEncode->weighted_p_pred = 0; // wpredp=2 | |
ctxEncode->bit_rate = 32000; | |
ctxEncode->width = clip_width; | |
ctxEncode->height = clip_height; | |
ctxEncode->time_base.num = 1; | |
ctxEncode->time_base.den = 30; | |
ctxEncode->pix_fmt = PIX_FMT_YUV420P; | |
ctxEncode->dsp_mask = (FF_MM_MMX | FF_MM_MMXEXT | FF_MM_SSE); | |
ctxEncode->rc_lookahead = 0; | |
ctxEncode->max_b_frames = 0; | |
ctxEncode->b_frame_strategy = 1; | |
ctxEncode->chromaoffset = 0; | |
ctxEncode->thread_count = 1; | |
ctxEncode->bit_rate = (int) (128000.0f * 0.80f); | |
ctxEncode->bit_rate_tolerance = (int) (128000.0f * 0.20f); | |
ctxEncode->gop_size = 30 * 3; // Each 3 seconds | |
} | |
void h264_encode(char* input_filename, char* output_filename) { | |
AVCodec* codecEncode; | |
AVCodecContext* ctxEncode = NULL; | |
FILE* fin; | |
FILE* fout; | |
AVFrame* pictureEncoded; | |
uint8_t* encoderOut; | |
uint8_t* picEncodeBuf; | |
int encoderOutSize; | |
int pic_size; | |
AVPacket avpkt; | |
int got_picture, len; | |
const int clip_width = 176; | |
const int clip_height = 144; | |
int frame = 0; | |
uint8_t* decodedOut; | |
codecEncode = avcodec_find_encoder(CODEC_ID_H264); | |
if (!codecEncode) { | |
printf("Codec not found.\n"); | |
exit(1); | |
} | |
init_encode_context(ctxEncode); | |
/* open codec for encoder*/ | |
if (avcodec_open(ctxEncode, codecEncode) < 0) { | |
printf("Could not open codec.\n"); | |
exit(1); | |
} | |
//open file to read | |
fin = fopen(input_filename, "rb"); | |
if (!fin) { | |
printf("Could not open file %s.\n", input_filename); | |
exit(1); | |
} | |
fout = fopen(output_filename, "w"); | |
/* alloc image and output buffer for encoder*/ | |
pictureEncoded = avcodec_alloc_frame(); | |
avcodec_get_frame_defaults(pictureEncoded); | |
//encoderOutSize = 100000; | |
encoderOut = (uint8_t*) malloc(100000); | |
//int size = ctxEncode->width * ctxEncode->height; | |
picEncodeBuf = (uint8_t*) malloc(3 * pic_size / 2); /* size for YUV 420 */ | |
pictureEncoded->data[0] = picEncodeBuf; | |
pictureEncoded->data[1] = pictureEncoded->data[0] + pic_size; | |
pictureEncoded->data[2] = pictureEncoded->data[1] + pic_size / 4; | |
pictureEncoded->linesize[0] = ctxEncode->width; | |
pictureEncoded->linesize[1] = ctxEncode->width / 2; | |
pictureEncoded->linesize[2] = ctxEncode->width / 2; | |
// encode loop | |
for(int i=0;i<30;i++) { | |
fflush(stdout); | |
//read qcif 1 frame to buufer | |
fread(pictureEncoded->data[0], ctxEncode->width * ctxEncode->height, 1, fin); | |
fread(pictureEncoded->data[1], ctxEncode->width * ctxEncode->height / 4, 1, fin); | |
fread(pictureEncoded->data[2], ctxEncode->width * ctxEncode->height / 4, 1, fin); | |
pictureEncoded->pts = AV_NOPTS_VALUE; | |
/* encode frame */ | |
encoderOutSize = avcodec_encode_video(ctxEncode, encoderOut, 100000, pictureEncoded); | |
printf("Encoding frame %3d (size=%5d).\n", i, encoderOutSize); | |
if (encoderOutSize <= 0) { | |
continue; | |
} | |
fwrite(encoderOut, encoderOutSize, 1, fout); | |
frame++; | |
// //send encoderOut to decoder | |
// avpkt.size = encoderOutSize; | |
// avpkt.data = encoderOut; | |
// //decode frame | |
// len = avcodec_decode_video2(ctxDecode, pictureDecoded, &got_picture, &avpkt); | |
// if (len < 0) { | |
// printf("Error while decoding frame %d.\n", frame); | |
// exit(1); | |
// } | |
// if (got_picture) { | |
// printf("len = %d saving frame %3d\n", len, frame); | |
// fflush(stdout); | |
// avpicture_layout( | |
// (AVPicture*) pictureDecoded, ctxDecode->pix_fmt, | |
// clip_width, clip_height, decodedOut, pic_size | |
// ); | |
// fwrite(decodedOut, pic_size, 1, fout); | |
// frame++; | |
// } | |
} | |
fclose(fout); | |
fclose(fin); | |
avcodec_close(ctxEncode); | |
avcodec_close(ctxDecode); | |
av_free(ctxEncode); | |
av_free(ctxDecode); | |
av_free(pictureEncoded); | |
av_free(pictureDecoded); | |
} | |
int main(int argc, char **argv) { | |
avcodec_init(); | |
avcodec_register_all(); | |
h264_encode(argv[1], "decoded.h264"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment