Skip to content

Instantly share code, notes, and snippets.

@Dimanaux
Created December 16, 2019 19:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dimanaux/3fe1402273b227898eb273bfefdbe249 to your computer and use it in GitHub Desktop.
Save Dimanaux/3fe1402273b227898eb273bfefdbe249 to your computer and use it in GitHub Desktop.
#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