Advertisement
lutza

Untitled

Nov 8th, 2011
198
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 9.74 KB | None | 0 0
  1. #include <stdio.h>
  2.  
  3. #include <libavformat/avformat.h>
  4. #include <libavcodec/avcodec.h>
  5. #include <libavutil/opt.h>
  6. #include <libswscale/swscale.h>
  7.  
  8. int main (int argc, char **argv)
  9. {
  10.     if (argc !=3)
  11.     {
  12.         fprintf(stderr, "Error: invalid arguments\n");
  13.         fprintf(stderr, "\tCorrect usage: %s <input-filename> <output-filename>\n", argv[0]);
  14.         exit(1);
  15.     }
  16.  
  17.     // initialize all formats and codecs
  18.     av_register_all();
  19.  
  20.     /// Set up input
  21.     const char *input_filename = argv[1];
  22.     // must be initialized to NULL or otherwise avformat_open_input() will segfault
  23.     AVFormatContext *input_context = NULL;
  24.  
  25.     // Get input file context
  26.     if ( avformat_open_input(&input_context, input_filename, NULL, NULL) != 0 )
  27.     {
  28.         fprintf(stderr, "Error: Couldn't open input file.\n");
  29.         exit(1);
  30.     }
  31.  
  32.     // Get streams information
  33.     if( avformat_find_stream_info(input_context, NULL) < 0 )
  34.     {
  35.         fprintf(stderr, "Error: Couldn't find stream information.\n");
  36.         exit(1);
  37.     }
  38.  
  39.     // debug: dump informations about input to stdout
  40.     av_dump_format(input_context, 0, input_filename, 0);
  41.  
  42.  
  43.     // Find the first video stream
  44.     int i, video_stream;
  45.     video_stream=-1;
  46.  
  47.     for(i=0; i<input_context->nb_streams; i++)
  48.     {
  49.         if(input_context->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
  50.         {
  51.             video_stream=i;
  52.             break;
  53.         }
  54.     }
  55.     if(video_stream==-1)
  56.     {
  57.         fprintf(stderr, "Error: Couldn't find a video stream.\n");
  58.         exit(1);
  59.     }
  60.  
  61.     // Get codec context for selected stream
  62.     AVCodecContext *iv_codec_ctx = input_context->streams[video_stream]->codec;
  63.     // Find the decoder for the video stream
  64.     AVCodec *v_decoder  = avcodec_find_decoder ( iv_codec_ctx->codec_id );
  65.     if(v_decoder==NULL)
  66.     {
  67.         fprintf(stderr, "Error: Video decoder not found.\n");
  68.         exit(1);
  69.     }
  70.  
  71.     // Inform the codec that we can handle truncated bitstreams -- i.e.,
  72.     // bitstreams where frame boundaries can fall in the middle of packets
  73.     if(v_decoder->capabilities & CODEC_CAP_TRUNCATED)
  74.         iv_codec_ctx->flags|=CODEC_FLAG_TRUNCATED;
  75.  
  76.     // Open decoder with desired setup
  77.     if ( avcodec_open(iv_codec_ctx, v_decoder) < 0 )
  78.     {
  79.         fprintf(stderr, "Error: Couldn't open video decoder.\n");
  80.         exit(1);
  81.     }
  82.  
  83.     /// Set up output
  84.     const char *output_filename = argv[2];
  85.     AVFormatContext *output_context;
  86.  
  87.     // Alloc and create output file context
  88.     //   tell avcodec that it will contain h264 video stream
  89.     avformat_alloc_output_context2(&output_context, NULL, "h264", NULL);
  90.     if (!output_context)
  91.     {
  92.         fprintf(stderr, "Error: Couldn't create context for output file.\n");
  93.         exit(1);
  94.     }
  95.  
  96.     //open output file
  97.     if ( avio_open(&output_context->pb, output_filename, AVIO_FLAG_WRITE) < 0 )
  98.     {
  99.         fprintf(stderr, "Error: Could not open '%s'\n", output_filename);
  100.         exit(1);
  101.     }
  102.  
  103.     // find coder for h264
  104.     AVCodec *v_coder = avcodec_find_encoder(CODEC_ID_H264);
  105.     if (!v_coder)
  106.     {
  107.         fprintf(stderr, "Error: Could not found h264 codec.\n");
  108.         exit(1);
  109.     }
  110.  
  111.     // add new stream encoded by this coder to ouput context
  112.     AVStream *ov_stream = avformat_new_stream(output_context, v_coder);
  113.     if (!ov_stream)
  114.     {
  115.         fprintf(stderr, "Error: Could not alloc stream.\n");
  116.         exit(1);
  117.     }
  118.  
  119.     // set up encoding parameters (codec context)
  120.     AVCodecContext *ov_codec_ctx = ov_stream->codec;
  121.     ov_codec_ctx->codec_id = CODEC_ID_H264;
  122.     ov_codec_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
  123.     /* put sample parameters */
  124.     ov_codec_ctx->bit_rate = 400000;
  125.     /* resolution must be a multiple of two */
  126.     ov_codec_ctx->width = 352;
  127.     ov_codec_ctx->height = 288;
  128.     /* frames per second */
  129.     ov_codec_ctx->time_base= //(AVRational){1,25};
  130.         iv_codec_ctx->time_base;
  131.     ov_codec_ctx->gop_size = 10; /* emit one intra frame every ten frames */
  132.     ov_codec_ctx->max_b_frames=2;
  133.     ov_codec_ctx->pix_fmt = PIX_FMT_YUV420P;
  134.  
  135.     // set h264 preset
  136.     if ( av_opt_set(ov_codec_ctx->priv_data, "preset", "slow", 0) )
  137.     {
  138.         fprintf(stderr, "Error: Could not set h264 preset.\n");
  139.         exit(1);
  140.     }
  141.  
  142.     // debug: dump informations about output to stdout
  143.     av_dump_format(output_context, 0, output_filename, 1);
  144.  
  145.     // open h264 codec
  146.     if (avcodec_open(ov_codec_ctx, v_coder) < 0)
  147.     {
  148.         fprintf(stderr, "Error: Could not open h264 codec.\n");
  149.         exit(1);
  150.     }
  151.  
  152.     // create output buffer for video
  153.     int video_outbuf_size = 200000;
  154.     uint8_t *video_outbuf = av_malloc(video_outbuf_size);
  155.  
  156.     // allocate output picture
  157.     AVFrame *output_picture = avcodec_alloc_frame();
  158.     int size = avpicture_get_size(ov_codec_ctx->pix_fmt, ov_codec_ctx->width, ov_codec_ctx->height);
  159.     uint8_t * output_picture_buf = av_malloc(size);
  160.     if (!output_picture || !output_picture_buf)
  161.     {
  162.         fprintf(stderr, "Error: Could not allocate output picture.\n");
  163.         exit(1);
  164.     }
  165.     avpicture_fill((AVPicture *)output_picture, output_picture_buf,
  166.                    ov_codec_ctx->pix_fmt, ov_codec_ctx->width, ov_codec_ctx->height);
  167.  
  168.     // create picture conversion context
  169.     struct SwsContext *img_convert_ctx =
  170.             sws_getContext( iv_codec_ctx->width, iv_codec_ctx->height, iv_codec_ctx->pix_fmt,
  171.                             ov_codec_ctx->width, ov_codec_ctx->height, ov_codec_ctx->pix_fmt,
  172.                             SWS_BICUBIC, NULL, NULL, NULL);
  173.  
  174.  
  175.  
  176.     AVFrame *input_picture = avcodec_alloc_frame();
  177.     int got_picture;
  178.     int len, out_size;
  179.     int picture_counter = 0;
  180.     AVPacket packet;
  181.     AVPacket output_packet;
  182.     //av_init_packet(&packet);
  183.     uint8_t * packet_start;
  184.  
  185.  
  186.     /* write the output stream header, if any */
  187.     av_write_header(output_context);
  188.  
  189.     while ( av_read_frame(input_context, &packet) >= 0 )
  190.     // grab packet from input file
  191.     {
  192.         if ( packet.stream_index == video_stream )
  193.         // care only for packets from desired video stream
  194.         {
  195.             // store ptr to packet data start
  196.             packet_start = packet.data;
  197.             while (packet.size > 0)
  198.             // decode data from packet
  199.             {
  200.                 len = avcodec_decode_video2( iv_codec_ctx, input_picture, &got_picture, &packet);
  201.                 //printf("[video packet]%d bytes decoded from packet, got_picture = %d\n", len, got_picture);
  202.                 if (len<0)
  203.                 {
  204.                     fprintf(stderr, "Error: While decoding picture.\n");
  205.                     exit(1);
  206.                 }
  207.                 if (got_picture)
  208.                 {
  209.                     // handle picture
  210.                     picture_counter++;
  211.                     // convert img to output img format
  212.                     sws_scale(img_convert_ctx, &input_picture->data, input_picture->linesize,
  213.                         0, ov_codec_ctx->height, &output_picture->data, output_picture->linesize);
  214.  
  215.                     // send image for encoding
  216.                     out_size = avcodec_encode_video(ov_codec_ctx, video_outbuf, video_outbuf_size, output_picture);
  217.                     printf("encoding frame %3d (size=%5d)\n", picture_counter, out_size);
  218.                     // encoder returned some data, lets write them into output file
  219.                     if (out_size>0)
  220.                     {
  221.                         av_init_packet(&output_packet);
  222.                         // todo: co je tohle ??
  223.                         if (ov_codec_ctx->coded_frame->pts != AV_NOPTS_VALUE)
  224.                             output_packet.pts=
  225.                                 av_rescale_q(ov_codec_ctx->coded_frame->pts, ov_codec_ctx->time_base, ov_stream->time_base);
  226.                         printf("pts = %lf,   ", (double)ov_stream->pts.val * ov_stream->time_base.num / ov_stream->time_base.den);
  227.                         printf("%d %d %d\n", ov_codec_ctx->coded_frame->pts, ov_codec_ctx->time_base, ov_stream->time_base);
  228.                         //output_packet.dts = AV_NOPTS_VALUE;
  229.                         if(ov_codec_ctx->coded_frame->key_frame)
  230.                             output_packet.flags |= AV_PKT_FLAG_KEY;
  231.                         output_packet.stream_index = ov_stream->index;
  232.                         output_packet.data = video_outbuf;
  233.                         output_packet.size = out_size;
  234.  
  235.                         /* write the compressed frame in the media file */
  236.                         if ( av_interleaved_write_frame(output_context, &output_packet)!= 0 )
  237.                         {
  238.                             fprintf(stderr, "Error: while writing video frame.\n");
  239.                             exit(1);
  240.                         }
  241.  
  242.                     }
  243.                 }
  244.                 packet.size -= len;
  245.                 packet.data += len;
  246.             }
  247.             // restore ptr to packet data start so it can get released correctly by AV
  248.             packet.data = packet_start;
  249.         }
  250.         av_free_packet(&packet);    // free packet
  251.     }
  252.  
  253.     printf("video frames grabbed = %d \n", picture_counter);
  254.  
  255.     // write output trailer if any
  256.     av_write_trailer(output_context);
  257.  
  258.     // clean resources
  259.  
  260.     // free output
  261.     avcodec_close(ov_stream->codec);
  262.     av_free(output_picture);
  263.     av_free(output_picture->data[0]);
  264.     av_free(video_outbuf);
  265.  
  266.     for(i = 0; i < output_context->nb_streams; i++) {
  267.         av_freep(&output_context->streams[i]->codec);
  268.         av_freep(&output_context->streams[i]);
  269.     }
  270.     av_free(output_context);
  271.  
  272.     // free input
  273.     avcodec_close(iv_codec_ctx);
  274.     av_close_input_file(input_context);
  275.     av_free(input_picture);
  276.  
  277.     return 0;
  278. }
  279.  
  280.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement