pkt->stream_index);
}
-static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt)
+static int write_frame(AVFormatContext *fmt_ctx, AVCodecContext *c,
+ AVStream *st, AVFrame *frame)
{
- /* rescale output packet timestamp values from codec to stream timebase */
- av_packet_rescale_ts(pkt, *time_base, st->time_base);
- pkt->stream_index = st->index;
+ int ret;
+
+ // send the frame to the encoder
+ ret = avcodec_send_frame(c, frame);
+ if (ret < 0) {
+ fprintf(stderr, "Error sending a frame to the encoder: %s\n",
+ av_err2str(ret));
+ exit(1);
+ }
+
+ while (ret >= 0) {
+ AVPacket pkt = { 0 };
- /* Write the compressed frame to the media file. */
- log_packet(fmt_ctx, pkt);
- return av_interleaved_write_frame(fmt_ctx, pkt);
+ ret = avcodec_receive_packet(c, &pkt);
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+ break;
+ else if (ret < 0) {
+ fprintf(stderr, "Error encoding a frame: %s\n", av_err2str(ret));
+ exit(1);
+ }
+
+ /* rescale output packet timestamp values from codec to stream timebase */
+ av_packet_rescale_ts(&pkt, c->time_base, st->time_base);
+ pkt.stream_index = st->index;
+
+ /* Write the compressed frame to the media file. */
+ log_packet(fmt_ctx, &pkt);
+ ret = av_interleaved_write_frame(fmt_ctx, &pkt);
+ av_packet_unref(&pkt);
+ if (ret < 0) {
+ fprintf(stderr, "Error while writing output packet: %s\n", av_err2str(ret));
+ exit(1);
+ }
+ }
+
+ return ret == AVERROR_EOF ? 1 : 0;
}
/* Add an output stream. */
static void add_stream(OutputStream *ost, AVFormatContext *oc,
- AVCodec **codec,
+ const AVCodec **codec,
enum AVCodecID codec_id)
{
AVCodecContext *c;
* the motion of the chroma plane does not match the luma plane. */
c->mb_decision = 2;
}
- break;
+ break;
default:
break;
return frame;
}
-static void open_audio(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
+static void open_audio(AVFormatContext *oc, const AVCodec *codec,
+ OutputStream *ost, AVDictionary *opt_arg)
{
AVCodecContext *c;
int nb_samples;
}
/* create resampler context */
- ost->swr_ctx = swr_alloc();
- if (!ost->swr_ctx) {
- fprintf(stderr, "Could not allocate resampler context\n");
- exit(1);
- }
+ ost->swr_ctx = swr_alloc();
+ if (!ost->swr_ctx) {
+ fprintf(stderr, "Could not allocate resampler context\n");
+ exit(1);
+ }
- /* set options */
- av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0);
- av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0);
- av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
- av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0);
- av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0);
- av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0);
-
- /* initialize the resampling context */
- if ((ret = swr_init(ost->swr_ctx)) < 0) {
- fprintf(stderr, "Failed to initialize the resampling context\n");
- exit(1);
- }
+ /* set options */
+ av_opt_set_int (ost->swr_ctx, "in_channel_count", c->channels, 0);
+ av_opt_set_int (ost->swr_ctx, "in_sample_rate", c->sample_rate, 0);
+ av_opt_set_sample_fmt(ost->swr_ctx, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
+ av_opt_set_int (ost->swr_ctx, "out_channel_count", c->channels, 0);
+ av_opt_set_int (ost->swr_ctx, "out_sample_rate", c->sample_rate, 0);
+ av_opt_set_sample_fmt(ost->swr_ctx, "out_sample_fmt", c->sample_fmt, 0);
+
+ /* initialize the resampling context */
+ if ((ret = swr_init(ost->swr_ctx)) < 0) {
+ fprintf(stderr, "Failed to initialize the resampling context\n");
+ exit(1);
+ }
}
/* Prepare a 16 bit dummy audio frame of 'frame_size' samples and
/* check if we want to generate more frames */
if (av_compare_ts(ost->next_pts, ost->enc->time_base,
- STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
+ STREAM_DURATION, (AVRational){ 1, 1 }) > 0)
return NULL;
for (j = 0; j <frame->nb_samples; j++) {
static int write_audio_frame(AVFormatContext *oc, OutputStream *ost)
{
AVCodecContext *c;
- AVPacket pkt = { 0 }; // data and size must be 0;
AVFrame *frame;
int ret;
- int got_packet;
int dst_nb_samples;
- av_init_packet(&pkt);
c = ost->enc;
frame = get_audio_frame(ost);
if (frame) {
/* convert samples from native format to destination codec format, using the resampler */
- /* compute destination number of samples */
- dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
- c->sample_rate, c->sample_rate, AV_ROUND_UP);
- av_assert0(dst_nb_samples == frame->nb_samples);
+ /* compute destination number of samples */
+ dst_nb_samples = av_rescale_rnd(swr_get_delay(ost->swr_ctx, c->sample_rate) + frame->nb_samples,
+ c->sample_rate, c->sample_rate, AV_ROUND_UP);
+ av_assert0(dst_nb_samples == frame->nb_samples);
/* when we pass a frame to the encoder, it may keep a reference to it
* internally;
ost->samples_count += dst_nb_samples;
}
- ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet);
- if (ret < 0) {
- fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret));
- exit(1);
- }
-
- if (got_packet) {
- ret = write_frame(oc, &c->time_base, ost->st, &pkt);
- if (ret < 0) {
- fprintf(stderr, "Error while writing audio frame: %s\n",
- av_err2str(ret));
- exit(1);
- }
- }
-
- return (frame || got_packet) ? 0 : 1;
+ return write_frame(oc, c, ost->st, frame);
}
/**************************************************************/
picture->height = height;
/* allocate the buffers for the frame data */
- ret = av_frame_get_buffer(picture, 32);
+ ret = av_frame_get_buffer(picture, 0);
if (ret < 0) {
fprintf(stderr, "Could not allocate frame data.\n");
exit(1);
return picture;
}
-static void open_video(AVFormatContext *oc, AVCodec *codec, OutputStream *ost, AVDictionary *opt_arg)
+static void open_video(AVFormatContext *oc, const AVCodec *codec,
+ OutputStream *ost, AVDictionary *opt_arg)
{
int ret;
AVCodecContext *c = ost->enc;
/* check if we want to generate more frames */
if (av_compare_ts(ost->next_pts, c->time_base,
- STREAM_DURATION, (AVRational){ 1, 1 }) >= 0)
+ STREAM_DURATION, (AVRational){ 1, 1 }) > 0)
return NULL;
/* when we pass a frame to the encoder, it may keep a reference to it
*/
static int write_video_frame(AVFormatContext *oc, OutputStream *ost)
{
- int ret;
- AVCodecContext *c;
- AVFrame *frame;
- int got_packet = 0;
- AVPacket pkt = { 0 };
-
- c = ost->enc;
-
- frame = get_video_frame(ost);
-
- av_init_packet(&pkt);
-
- /* encode the image */
- ret = avcodec_encode_video2(c, &pkt, frame, &got_packet);
- if (ret < 0) {
- fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret));
- exit(1);
- }
-
- if (got_packet) {
- ret = write_frame(oc, &c->time_base, ost->st, &pkt);
- } else {
- ret = 0;
- }
-
- if (ret < 0) {
- fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret));
- exit(1);
- }
-
- return (frame || got_packet) ? 0 : 1;
+ return write_frame(oc, ost->enc, ost->st, get_video_frame(ost));
}
static void close_stream(AVFormatContext *oc, OutputStream *ost)
int main(int argc, char **argv)
{
OutputStream video_st = { 0 }, audio_st = { 0 };
+ const AVOutputFormat *fmt;
const char *filename;
- AVOutputFormat *fmt;
AVFormatContext *oc;
- AVCodec *audio_codec, *video_codec;
+ const AVCodec *audio_codec, *video_codec;
int ret;
int have_video = 0, have_audio = 0;
int encode_video = 0, encode_audio = 0;