-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add encoder * fix reviews * Add gop_size and max_b_frames options * add profile option * add tests * improve test
- Loading branch information
Showing
15 changed files
with
710 additions
and
13 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
#include "encoder.h" | ||
|
||
struct Encoder *encoder_alloc() { | ||
struct Encoder *encoder = XAV_ALLOC(sizeof(struct Encoder)); | ||
encoder->c = NULL; | ||
encoder->codec = NULL; | ||
encoder->num_packets = 0; | ||
encoder->max_num_packets = 8; | ||
encoder->packets = XAV_ALLOC(encoder->max_num_packets * sizeof(AVPacket *)); | ||
|
||
for (int i = 0; i < encoder->max_num_packets; i++) { | ||
encoder->packets[i] = av_packet_alloc(); | ||
} | ||
|
||
return encoder; | ||
} | ||
|
||
int encoder_init(struct Encoder *encoder, struct EncoderConfig *config) { | ||
encoder->codec = avcodec_find_encoder(config->codec); | ||
if (!encoder->codec) { | ||
return -1; | ||
} | ||
|
||
encoder->c = avcodec_alloc_context3(encoder->codec); | ||
if (!encoder->c) { | ||
return -1; | ||
} | ||
|
||
encoder->c->width = config->width; | ||
encoder->c->height = config->height; | ||
encoder->c->pix_fmt = config->format; | ||
encoder->c->time_base = config->time_base; | ||
|
||
if (config->profile != FF_PROFILE_UNKNOWN) { | ||
encoder->c->profile = config->profile; | ||
} | ||
|
||
if (config->gop_size > 0) { | ||
encoder->c->gop_size = config->gop_size; | ||
} | ||
|
||
if (config->max_b_frames >= 0) { | ||
encoder->c->max_b_frames = config->max_b_frames; | ||
} | ||
|
||
AVDictionary *opts = NULL; | ||
if (config->codec == AV_CODEC_ID_HEVC) { | ||
char x265_params[256] = "log-level=warning"; | ||
if (config->gop_size > 0) { | ||
sprintf(x265_params + strlen(x265_params), ":keyint=%d", config->gop_size); | ||
} | ||
|
||
if (config->max_b_frames >= 0) { | ||
sprintf(x265_params + strlen(x265_params), ":bframes=%d", config->max_b_frames); | ||
} | ||
|
||
av_dict_set(&opts, "x265-params", x265_params, 0); | ||
} | ||
|
||
return avcodec_open2(encoder->c, encoder->codec, &opts); | ||
} | ||
|
||
int encoder_encode(struct Encoder *encoder, AVFrame *frame) { | ||
int ret = avcodec_send_frame(encoder->c, frame); | ||
if (ret < 0) { | ||
return ret; | ||
} | ||
|
||
encoder->num_packets = 0; | ||
|
||
while (1) { | ||
ret = avcodec_receive_packet(encoder->c, encoder->packets[encoder->num_packets]); | ||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { | ||
break; | ||
} else if (ret < 0) { | ||
return ret; | ||
} | ||
|
||
if (++encoder->num_packets >= encoder->max_num_packets) { | ||
encoder->max_num_packets *= 2; | ||
encoder->packets = | ||
XAV_REALLOC(encoder->packets, encoder->max_num_packets * sizeof(AVPacket *)); | ||
for (int i = encoder->num_packets; i < encoder->max_num_packets; i++) { | ||
encoder->packets[i] = av_packet_alloc(); | ||
} | ||
} | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
void encoder_free(struct Encoder **encoder) { | ||
if (*encoder != NULL) { | ||
struct Encoder *e = *encoder; | ||
|
||
if (e->c != NULL) { | ||
avcodec_free_context(&e->c); | ||
} | ||
|
||
for (int i = 0; i < e->max_num_packets; i++) { | ||
av_packet_free(&e->packets[i]); | ||
} | ||
|
||
XAV_FREE(e); | ||
*encoder = NULL; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#include "utils.h" | ||
#include <libavcodec/avcodec.h> | ||
|
||
struct Encoder { | ||
const AVCodec *codec; | ||
AVCodecContext *c; | ||
int num_packets; | ||
int max_num_packets; | ||
AVPacket **packets; | ||
}; | ||
|
||
struct EncoderConfig { | ||
enum AVMediaType media_type; | ||
enum AVCodecID codec; | ||
int width; | ||
int height; | ||
enum AVPixelFormat format; | ||
AVRational time_base; | ||
int gop_size; | ||
int max_b_frames; | ||
int profile; | ||
}; | ||
|
||
struct Encoder *encoder_alloc(); | ||
|
||
int encoder_init(struct Encoder *encoder, struct EncoderConfig *encoder_config); | ||
|
||
int encoder_encode(struct Encoder *encoder, AVFrame *frame); | ||
|
||
void encoder_free(struct Encoder **encoder); |
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
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
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
Oops, something went wrong.