X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=output_example.c;h=45f6a0645b70c593949f29287315848515b342ed;hb=14e2a9404e25ffd80e84b1b7a152858c63b2d690;hp=0e06b0cbb619246b7e18821a8d8323fabfd70f2a;hpb=e70fcf075b8f92c4e410b80c703fbdc1d531d42d;p=ffmpeg diff --git a/output_example.c b/output_example.c index 0e06b0cbb61..45f6a0645b7 100644 --- a/output_example.c +++ b/output_example.c @@ -24,13 +24,19 @@ */ #include #include +#include #include +#ifndef M_PI +#define M_PI 3.1415926535897931 +#endif + #include "avformat.h" /* 5 seconds stream duration */ -#define STREAM_DURATION 5.0 - +#define STREAM_DURATION 5.0 +#define STREAM_FRAME_RATE 25 /* 25 images/s */ +#define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE)) /**************************************************************/ /* audio output */ @@ -115,21 +121,33 @@ void open_audio(AVFormatContext *oc, AVStream *st) samples = malloc(audio_input_frame_size * 2 * c->channels); } +/* prepare a 16 bit dummy audio frame of 'frame_size' samples and + 'nb_channels' channels */ +void get_audio_frame(int16_t *samples, int frame_size, int nb_channels) +{ + int j, i, v; + int16_t *q; + + q = samples; + for(j=0;jcodec; - for(j=0;jchannels); + out_size = avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples); /* write the compressed frame in the media file */ @@ -176,10 +194,23 @@ AVStream *add_video_stream(AVFormatContext *oc, int codec_id) c->width = 352; c->height = 288; /* frames per second */ - c->frame_rate = 25; - c->frame_rate_base= 1; - c->gop_size = 12; /* emit one intra frame every twelve frames */ - + c->frame_rate = STREAM_FRAME_RATE; + c->frame_rate_base = 1; + c->gop_size = 12; /* emit one intra frame every twelve frames at most */ + if (c->codec_id == CODEC_ID_MPEG2VIDEO) { + /* just for testing, we also add B frames */ + c->max_b_frames = 2; + } + if (c->codec_id == CODEC_ID_MPEG1VIDEO){ + /* needed to avoid using macroblocks in which some coeffs overflow + this doesnt happen with normal video, it just happens here as the + motion of the chroma plane doesnt match the luma plane */ + c->mb_decision=2; + } + // some formats want stream headers to be seperate + if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp")) + c->flags |= CODEC_FLAG_GLOBAL_HEADER; + return st; } @@ -278,18 +309,27 @@ void write_video_frame(AVFormatContext *oc, AVStream *st) { int out_size, ret; AVCodecContext *c; - + AVFrame *picture_ptr; + c = &st->codec; - if (c->pix_fmt != PIX_FMT_YUV420P) { - /* as we only generate a YUV420P picture, we must convert it - to the codec pixel format if needed */ - fill_yuv_image(tmp_picture, frame_count, c->width, c->height); - img_convert((AVPicture *)picture, c->pix_fmt, - (AVPicture *)tmp_picture, PIX_FMT_YUV420P, - c->width, c->height); + if (frame_count >= STREAM_NB_FRAMES) { + /* no more frame to compress. The codec has a latency of a few + frames if using B frames, so we get the last frames by + passing a NULL picture */ + picture_ptr = NULL; } else { - fill_yuv_image(picture, frame_count, c->width, c->height); + if (c->pix_fmt != PIX_FMT_YUV420P) { + /* as we only generate a YUV420P picture, we must convert it + to the codec pixel format if needed */ + fill_yuv_image(tmp_picture, frame_count, c->width, c->height); + img_convert((AVPicture *)picture, c->pix_fmt, + (AVPicture *)tmp_picture, PIX_FMT_YUV420P, + c->width, c->height); + } else { + fill_yuv_image(picture, frame_count, c->width, c->height); + } + picture_ptr = picture; } @@ -297,13 +337,18 @@ void write_video_frame(AVFormatContext *oc, AVStream *st) /* raw video case. The API will change slightly in the near futur for that */ ret = av_write_frame(oc, st->index, - (uint8_t *)picture, sizeof(AVPicture)); + (uint8_t *)picture_ptr, sizeof(AVPicture)); } else { /* encode the image */ - out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture); - - /* write the compressed frame in the media file */ - ret = av_write_frame(oc, st->index, video_outbuf, out_size); + out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture_ptr); + /* if zero size, it means the image was buffered */ + if (out_size != 0) { + /* write the compressed frame in the media file */ + /* XXX: in case of B frames, the pts is not yet valid */ + ret = av_write_frame(oc, st->index, video_outbuf, out_size); + } else { + ret = 0; + } } if (ret != 0) { fprintf(stderr, "Error while writing video frame\n"); @@ -363,7 +408,7 @@ int main(int argc, char **argv) } /* allocate the output media context */ - oc = av_mallocz(sizeof(AVFormatContext)); + oc = av_alloc_format_context(); if (!oc) { fprintf(stderr, "Memory error\n"); exit(1);