00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032 #include <math.h>
00033
00034 #include "libavformat/avformat.h"
00035 #include "libswscale/swscale.h"
00036
00037 #undef exit
00038
00039
00040 #define STREAM_DURATION 5.0
00041 #define STREAM_FRAME_RATE 25
00042 #define STREAM_NB_FRAMES ((int)(STREAM_DURATION * STREAM_FRAME_RATE))
00043 #define STREAM_PIX_FMT PIX_FMT_YUV420P
00044
00045 static int sws_flags = SWS_BICUBIC;
00046
00047
00048
00049
00050 float t, tincr, tincr2;
00051 int16_t *samples;
00052 uint8_t *audio_outbuf;
00053 int audio_outbuf_size;
00054 int audio_input_frame_size;
00055
00056
00057
00058
00059 static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id)
00060 {
00061 AVCodecContext *c;
00062 AVStream *st;
00063
00064 st = av_new_stream(oc, 1);
00065 if (!st) {
00066 fprintf(stderr, "Could not alloc stream\n");
00067 exit(1);
00068 }
00069
00070 c = st->codec;
00071 c->codec_id = codec_id;
00072 c->codec_type = AVMEDIA_TYPE_AUDIO;
00073
00074
00075 c->sample_fmt = AV_SAMPLE_FMT_S16;
00076 c->bit_rate = 64000;
00077 c->sample_rate = 44100;
00078 c->channels = 2;
00079
00080
00081 if(oc->oformat->flags & AVFMT_GLOBALHEADER)
00082 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
00083
00084 return st;
00085 }
00086
00087 static void open_audio(AVFormatContext *oc, AVStream *st)
00088 {
00089 AVCodecContext *c;
00090 AVCodec *codec;
00091
00092 c = st->codec;
00093
00094
00095 codec = avcodec_find_encoder(c->codec_id);
00096 if (!codec) {
00097 fprintf(stderr, "codec not found\n");
00098 exit(1);
00099 }
00100
00101
00102 if (avcodec_open(c, codec) < 0) {
00103 fprintf(stderr, "could not open codec\n");
00104 exit(1);
00105 }
00106
00107
00108 t = 0;
00109 tincr = 2 * M_PI * 110.0 / c->sample_rate;
00110
00111 tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate;
00112
00113 audio_outbuf_size = 10000;
00114 audio_outbuf = av_malloc(audio_outbuf_size);
00115
00116
00117
00118 if (c->frame_size <= 1) {
00119 audio_input_frame_size = audio_outbuf_size / c->channels;
00120 switch(st->codec->codec_id) {
00121 case CODEC_ID_PCM_S16LE:
00122 case CODEC_ID_PCM_S16BE:
00123 case CODEC_ID_PCM_U16LE:
00124 case CODEC_ID_PCM_U16BE:
00125 audio_input_frame_size >>= 1;
00126 break;
00127 default:
00128 break;
00129 }
00130 } else {
00131 audio_input_frame_size = c->frame_size;
00132 }
00133 samples = av_malloc(audio_input_frame_size * 2 * c->channels);
00134 }
00135
00136
00137
00138 static void get_audio_frame(int16_t *samples, int frame_size, int nb_channels)
00139 {
00140 int j, i, v;
00141 int16_t *q;
00142
00143 q = samples;
00144 for(j=0;j<frame_size;j++) {
00145 v = (int)(sin(t) * 10000);
00146 for(i = 0; i < nb_channels; i++)
00147 *q++ = v;
00148 t += tincr;
00149 tincr += tincr2;
00150 }
00151 }
00152
00153 static void write_audio_frame(AVFormatContext *oc, AVStream *st)
00154 {
00155 AVCodecContext *c;
00156 AVPacket pkt;
00157 av_init_packet(&pkt);
00158
00159 c = st->codec;
00160
00161 get_audio_frame(samples, audio_input_frame_size, c->channels);
00162
00163 pkt.size= avcodec_encode_audio(c, audio_outbuf, audio_outbuf_size, samples);
00164
00165 if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE)
00166 pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
00167 pkt.flags |= AV_PKT_FLAG_KEY;
00168 pkt.stream_index= st->index;
00169 pkt.data= audio_outbuf;
00170
00171
00172 if (av_interleaved_write_frame(oc, &pkt) != 0) {
00173 fprintf(stderr, "Error while writing audio frame\n");
00174 exit(1);
00175 }
00176 }
00177
00178 static void close_audio(AVFormatContext *oc, AVStream *st)
00179 {
00180 avcodec_close(st->codec);
00181
00182 av_free(samples);
00183 av_free(audio_outbuf);
00184 }
00185
00186
00187
00188
00189 AVFrame *picture, *tmp_picture;
00190 uint8_t *video_outbuf;
00191 int frame_count, video_outbuf_size;
00192
00193
00194 static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id)
00195 {
00196 AVCodecContext *c;
00197 AVStream *st;
00198
00199 st = av_new_stream(oc, 0);
00200 if (!st) {
00201 fprintf(stderr, "Could not alloc stream\n");
00202 exit(1);
00203 }
00204
00205 c = st->codec;
00206 c->codec_id = codec_id;
00207 c->codec_type = AVMEDIA_TYPE_VIDEO;
00208
00209
00210 c->bit_rate = 400000;
00211
00212 c->width = 352;
00213 c->height = 288;
00214
00215
00216
00217
00218 c->time_base.den = STREAM_FRAME_RATE;
00219 c->time_base.num = 1;
00220 c->gop_size = 12;
00221 c->pix_fmt = STREAM_PIX_FMT;
00222 if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
00223
00224 c->max_b_frames = 2;
00225 }
00226 if (c->codec_id == CODEC_ID_MPEG1VIDEO){
00227
00228
00229
00230 c->mb_decision=2;
00231 }
00232
00233 if(oc->oformat->flags & AVFMT_GLOBALHEADER)
00234 c->flags |= CODEC_FLAG_GLOBAL_HEADER;
00235
00236 return st;
00237 }
00238
00239 static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height)
00240 {
00241 AVFrame *picture;
00242 uint8_t *picture_buf;
00243 int size;
00244
00245 picture = avcodec_alloc_frame();
00246 if (!picture)
00247 return NULL;
00248 size = avpicture_get_size(pix_fmt, width, height);
00249 picture_buf = av_malloc(size);
00250 if (!picture_buf) {
00251 av_free(picture);
00252 return NULL;
00253 }
00254 avpicture_fill((AVPicture *)picture, picture_buf,
00255 pix_fmt, width, height);
00256 return picture;
00257 }
00258
00259 static void open_video(AVFormatContext *oc, AVStream *st)
00260 {
00261 AVCodec *codec;
00262 AVCodecContext *c;
00263
00264 c = st->codec;
00265
00266
00267 codec = avcodec_find_encoder(c->codec_id);
00268 if (!codec) {
00269 fprintf(stderr, "codec not found\n");
00270 exit(1);
00271 }
00272
00273
00274 if (avcodec_open(c, codec) < 0) {
00275 fprintf(stderr, "could not open codec\n");
00276 exit(1);
00277 }
00278
00279 video_outbuf = NULL;
00280 if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
00281
00282
00283
00284
00285
00286
00287 video_outbuf_size = 200000;
00288 video_outbuf = av_malloc(video_outbuf_size);
00289 }
00290
00291
00292 picture = alloc_picture(c->pix_fmt, c->width, c->height);
00293 if (!picture) {
00294 fprintf(stderr, "Could not allocate picture\n");
00295 exit(1);
00296 }
00297
00298
00299
00300
00301 tmp_picture = NULL;
00302 if (c->pix_fmt != PIX_FMT_YUV420P) {
00303 tmp_picture = alloc_picture(PIX_FMT_YUV420P, c->width, c->height);
00304 if (!tmp_picture) {
00305 fprintf(stderr, "Could not allocate temporary picture\n");
00306 exit(1);
00307 }
00308 }
00309 }
00310
00311
00312 static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
00313 {
00314 int x, y, i;
00315
00316 i = frame_index;
00317
00318
00319 for(y=0;y<height;y++) {
00320 for(x=0;x<width;x++) {
00321 pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
00322 }
00323 }
00324
00325
00326 for(y=0;y<height/2;y++) {
00327 for(x=0;x<width/2;x++) {
00328 pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
00329 pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
00330 }
00331 }
00332 }
00333
00334 static void write_video_frame(AVFormatContext *oc, AVStream *st)
00335 {
00336 int out_size, ret;
00337 AVCodecContext *c;
00338 static struct SwsContext *img_convert_ctx;
00339
00340 c = st->codec;
00341
00342 if (frame_count >= STREAM_NB_FRAMES) {
00343
00344
00345
00346 } else {
00347 if (c->pix_fmt != PIX_FMT_YUV420P) {
00348
00349
00350 if (img_convert_ctx == NULL) {
00351 img_convert_ctx = sws_getContext(c->width, c->height,
00352 PIX_FMT_YUV420P,
00353 c->width, c->height,
00354 c->pix_fmt,
00355 sws_flags, NULL, NULL, NULL);
00356 if (img_convert_ctx == NULL) {
00357 fprintf(stderr, "Cannot initialize the conversion context\n");
00358 exit(1);
00359 }
00360 }
00361 fill_yuv_image(tmp_picture, frame_count, c->width, c->height);
00362 sws_scale(img_convert_ctx, tmp_picture->data, tmp_picture->linesize,
00363 0, c->height, picture->data, picture->linesize);
00364 } else {
00365 fill_yuv_image(picture, frame_count, c->width, c->height);
00366 }
00367 }
00368
00369
00370 if (oc->oformat->flags & AVFMT_RAWPICTURE) {
00371
00372
00373 AVPacket pkt;
00374 av_init_packet(&pkt);
00375
00376 pkt.flags |= AV_PKT_FLAG_KEY;
00377 pkt.stream_index= st->index;
00378 pkt.data= (uint8_t *)picture;
00379 pkt.size= sizeof(AVPicture);
00380
00381 ret = av_interleaved_write_frame(oc, &pkt);
00382 } else {
00383
00384 out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture);
00385
00386 if (out_size > 0) {
00387 AVPacket pkt;
00388 av_init_packet(&pkt);
00389
00390 if (c->coded_frame->pts != AV_NOPTS_VALUE)
00391 pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
00392 if(c->coded_frame->key_frame)
00393 pkt.flags |= AV_PKT_FLAG_KEY;
00394 pkt.stream_index= st->index;
00395 pkt.data= video_outbuf;
00396 pkt.size= out_size;
00397
00398
00399 ret = av_interleaved_write_frame(oc, &pkt);
00400 } else {
00401 ret = 0;
00402 }
00403 }
00404 if (ret != 0) {
00405 fprintf(stderr, "Error while writing video frame\n");
00406 exit(1);
00407 }
00408 frame_count++;
00409 }
00410
00411 static void close_video(AVFormatContext *oc, AVStream *st)
00412 {
00413 avcodec_close(st->codec);
00414 av_free(picture->data[0]);
00415 av_free(picture);
00416 if (tmp_picture) {
00417 av_free(tmp_picture->data[0]);
00418 av_free(tmp_picture);
00419 }
00420 av_free(video_outbuf);
00421 }
00422
00423
00424
00425
00426 int main(int argc, char **argv)
00427 {
00428 const char *filename;
00429 AVOutputFormat *fmt;
00430 AVFormatContext *oc;
00431 AVStream *audio_st, *video_st;
00432 double audio_pts, video_pts;
00433 int i;
00434
00435
00436 av_register_all();
00437
00438 if (argc != 2) {
00439 printf("usage: %s output_file\n"
00440 "API example program to output a media file with libavformat.\n"
00441 "The output format is automatically guessed according to the file extension.\n"
00442 "Raw images can also be output by using '%%d' in the filename\n"
00443 "\n", argv[0]);
00444 exit(1);
00445 }
00446
00447 filename = argv[1];
00448
00449
00450 avformat_alloc_output_context2(&oc, NULL, NULL, filename);
00451 if (!oc) {
00452 printf("Could not deduce output format from file extension: using MPEG.\n");
00453 avformat_alloc_output_context2(&oc, NULL, "mpeg", filename);
00454 }
00455 if (!oc) {
00456 exit(1);
00457 }
00458 fmt= oc->oformat;
00459
00460
00461
00462 video_st = NULL;
00463 audio_st = NULL;
00464 if (fmt->video_codec != CODEC_ID_NONE) {
00465 video_st = add_video_stream(oc, fmt->video_codec);
00466 }
00467 if (fmt->audio_codec != CODEC_ID_NONE) {
00468 audio_st = add_audio_stream(oc, fmt->audio_codec);
00469 }
00470
00471 av_dump_format(oc, 0, filename, 1);
00472
00473
00474
00475 if (video_st)
00476 open_video(oc, video_st);
00477 if (audio_st)
00478 open_audio(oc, audio_st);
00479
00480
00481 if (!(fmt->flags & AVFMT_NOFILE)) {
00482 if (avio_open(&oc->pb, filename, AVIO_WRONLY) < 0) {
00483 fprintf(stderr, "Could not open '%s'\n", filename);
00484 exit(1);
00485 }
00486 }
00487
00488
00489 av_write_header(oc);
00490
00491 for(;;) {
00492
00493 if (audio_st)
00494 audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den;
00495 else
00496 audio_pts = 0.0;
00497
00498 if (video_st)
00499 video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den;
00500 else
00501 video_pts = 0.0;
00502
00503 if ((!audio_st || audio_pts >= STREAM_DURATION) &&
00504 (!video_st || video_pts >= STREAM_DURATION))
00505 break;
00506
00507
00508 if (!video_st || (video_st && audio_st && audio_pts < video_pts)) {
00509 write_audio_frame(oc, audio_st);
00510 } else {
00511 write_video_frame(oc, video_st);
00512 }
00513 }
00514
00515
00516
00517
00518
00519 av_write_trailer(oc);
00520
00521
00522 if (video_st)
00523 close_video(oc, video_st);
00524 if (audio_st)
00525 close_audio(oc, audio_st);
00526
00527
00528 for(i = 0; i < oc->nb_streams; i++) {
00529 av_freep(&oc->streams[i]->codec);
00530 av_freep(&oc->streams[i]);
00531 }
00532
00533 if (!(fmt->flags & AVFMT_NOFILE)) {
00534
00535 avio_close(oc->pb);
00536 }
00537
00538
00539 av_free(oc);
00540
00541 return 0;
00542 }