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