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