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