Advertisement
Guest User

libavfilter scale and convert format

a guest
Jun 18th, 2012
155
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.64 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <libavformat/avformat.h>
  4. #include <libavcodec/avcodec.h>
  5. #include <libavdevice/avdevice.h>
  6. #include <libswscale/swscale.h>
  7.  
  8. // filters
  9. #include <libavfilter/avfilter.h>
  10. #include <libavfilter/avfiltergraph.h>
  11. #include <libavfilter/buffersink.h>
  12. #include <libavfilter/avcodec.h>
  13.  
  14. int main(int argc, char **argv)
  15. {
  16.   if (argc < 3) {
  17.     fprintf(stderr,"usage: %s input-file format\n",argv[0]);
  18.     exit(1);
  19.   }
  20.  
  21.   // Prepare ffmpeg library
  22.   av_register_all();
  23.   avdevice_register_all();
  24.   avfilter_register_all();
  25.   avformat_network_init();
  26.  
  27.   // Open video stream
  28.   AVInputFormat *pIFormat = av_find_input_format(argv[2]);
  29.  
  30.   AVDictionary *params = NULL;
  31.  
  32.   if (strcmp(argv[2],"video4linux") == 0) {
  33.     av_dict_set(&params,"video_size","640x240",0);
  34.     av_dict_set(&params,"standard","ntsc",0);
  35.   }
  36.  
  37.   AVFormatContext *pIFormatCtx = NULL;
  38.  
  39.   int bRet = avformat_open_input(&pIFormatCtx, argv[1], pIFormat, &params);
  40.  
  41.   if (bRet != 0) {
  42.       fprintf(stderr, "Could not open file\n");
  43.       return 1;
  44.   }
  45.  
  46.   /* Retrieve stream information */
  47.   if (avformat_find_stream_info(pIFormatCtx,NULL) < 0) {
  48.       fprintf(stderr, "No stream info\n");
  49.       return 1;
  50.   }
  51.  
  52.   /* Find the first video stream */
  53.   int ixInputStream = -1;
  54.   int ix;
  55.   for (ix = 0; ix < pIFormatCtx->nb_streams; ix++) {
  56.       if (pIFormatCtx->streams[ix]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
  57.           ixInputStream = ix;
  58.           break;
  59.       }
  60.   }
  61.   if (ixInputStream == -1) {
  62.       fprintf(stderr, "No video stream in file\n");
  63.       return 1;
  64.   }
  65.  
  66.   /* Get a pointer to the codec pICodecCtx for the video stream */
  67.   AVCodecContext *pICodecCtx = pIFormatCtx->streams[ixInputStream]->codec;
  68.  
  69.   /* Find the decoder for the video stream */
  70.   AVCodec *pICodec = avcodec_find_decoder(pICodecCtx->codec_id);
  71.   if (!pICodec) {
  72.       fprintf(stderr, "Codec not found\n");
  73.       return 1;
  74.   }
  75.  
  76.   /* Open input codec */
  77.   if (avcodec_open2(pICodecCtx, pICodec,NULL) < 0) {
  78.       fprintf(stderr, "Could not open codec\n");
  79.       return 1;
  80.   }
  81.  
  82.   AVPacket inputPacket;
  83.  
  84.   /* Get 1 frame from input */
  85.   av_init_packet(&inputPacket);
  86.  
  87.   bRet = av_read_frame(pIFormatCtx, &inputPacket);
  88.  
  89.   if (bRet < 0) {
  90.     fprintf(stderr, "Could not read frame\n");
  91.     return 1;
  92.   }
  93.  
  94.   if (inputPacket.stream_index != ixInputStream) {
  95.     fprintf(stderr, "Packet is not for our stream\n");
  96.     return 1;
  97.   }
  98.  
  99.   /* Allocate video frame */
  100.   AVFrame *pFrame = avcodec_alloc_frame();
  101.  
  102.   /* Determine required buffer size and allocate buffer */
  103.   int szBuffer = avpicture_get_size(pICodecCtx->pix_fmt, pICodecCtx->width, pICodecCtx->height);
  104.   uint8_t *pBuffer = av_mallocz(szBuffer);
  105.  
  106.   /* Decode video frame */
  107.   int got_frame = 0;
  108.   int e = avcodec_decode_video2(pICodecCtx, pFrame, &got_frame,&inputPacket);
  109.  
  110.   av_free_packet(&inputPacket);
  111.  
  112.   if (!got_frame) {
  113.     fprintf(stderr, "Error reading frame\n");
  114.     return 1;
  115.   }
  116.  
  117.   pFrame->pts = 1;
  118.  
  119.   /* ------------------------------------------------------------------------------------ */
  120.  
  121.   // description of the filter
  122.   // TODO: write here the filter description
  123.   const char *filter_desc = "format=rgb24,scale=iw/2:ih/2";
  124.  
  125.   /* ---------------------------------------------------------------------------- */
  126.   /* Init the filter */
  127.   AVFilterGraph *filter_graph = avfilter_graph_alloc();
  128.   AVFilterContext *buffersink_ctx = NULL;
  129.   AVFilterContext *buffersrc_ctx = NULL;
  130.   AVFilterContext *format_ctx = NULL;
  131.   {
  132.     char args[512];
  133.    
  134.     AVFilterInOut *outputs = avfilter_inout_alloc();
  135.     AVFilterInOut *inputs  = avfilter_inout_alloc();
  136.    
  137.     enum PixelFormat pix_fmts[] = { pICodecCtx->pix_fmt, PIX_FMT_NONE };
  138.    
  139.     /* buffer video source: the decoded frames from the decoder will be inserted here. */
  140.     snprintf(args, sizeof(args), "%d:%d:%d:%d:%d:%d:%d:flags=%d",
  141.               pICodecCtx->width, pICodecCtx->height, pICodecCtx->pix_fmt,
  142.               pICodecCtx->time_base.num, pICodecCtx->time_base.den,
  143.               pICodecCtx->sample_aspect_ratio.num, pICodecCtx->sample_aspect_ratio.den,
  144.               SWS_BILINEAR
  145.             );
  146.    
  147.     int ret = avfilter_graph_create_filter(&buffersrc_ctx, avfilter_get_by_name("buffer"), "in",
  148.                                         args, NULL, filter_graph);
  149.     if (ret < 0) {
  150.         av_log(NULL, AV_LOG_ERROR, "Cannot create buffer source\n");
  151.         return ret;
  152.     }
  153.  
  154.     /* buffer video sink: to terminate the filter chain. */
  155.     ret = avfilter_graph_create_filter(&buffersink_ctx, avfilter_get_by_name("buffersink"), "out",
  156.                                         NULL, pix_fmts, filter_graph);
  157.     if (ret < 0) {
  158.         av_log(NULL, AV_LOG_ERROR, "Cannot create buffer sink\n");
  159.         return ret;
  160.     }
  161.    
  162.     /* Endpoints for the filter graph. */
  163.     outputs->name       = av_strdup("in");
  164.     outputs->filter_ctx = buffersrc_ctx;
  165.     outputs->pad_idx    = 0;
  166.     outputs->next       = NULL;
  167.  
  168.     inputs->name       = av_strdup("out");
  169.     inputs->filter_ctx = buffersink_ctx;
  170.     inputs->pad_idx    = 0;
  171.     inputs->next       = NULL;
  172.  
  173.     if (avfilter_graph_parse(filter_graph, filter_desc,&inputs, &outputs,NULL) < 0) {
  174.      fprintf(stderr, "Could init filters\n");
  175.       return 1;                                    
  176.     }
  177.    
  178.  
  179.     if (avfilter_graph_config(filter_graph, NULL) < 0) {
  180.       fprintf(stderr, "Could init filters II\n");
  181.       return 1;    
  182.     }
  183.   }
  184.  
  185.   /* ---------------------------------------------------------------------------- */
  186.  
  187.   // Apply the filter in one frame
  188.   if (av_vsrc_buffer_add_frame(buffersrc_ctx,pFrame,0) < 0) {
  189.     fprintf(stderr, "Error reading frame II\n");
  190.     return 1;      
  191.   }
  192.  
  193.   if (avfilter_poll_frame(buffersink_ctx->inputs[0])<0) {
  194.     fprintf(stderr, "Error applying filter frame\n");
  195.     return 1;
  196.   }
  197.  
  198.   AVFilterBufferRef *picref = NULL;
  199.  
  200.   if (av_buffersink_get_buffer_ref(buffersink_ctx,&picref,0) > 0 || !picref) {
  201.     fprintf(stderr, "Error applying filter frame II\n");
  202.     return 1;
  203.   }
  204.  
  205.   // frame in jpeg
  206.   AVFrame *finalFrame = avcodec_alloc_frame();
  207.  
  208.   // copy the filtered picture to the final frame
  209.   bRet = avfilter_fill_frame_from_buffer_ref(finalFrame,picref);
  210.  
  211.   if (bRet) {
  212.     fprintf(stderr, "Error copyng filter to frame\n");
  213.     return 1;
  214.   }
  215.  
  216.   /* ----------------------------------------------------------------------------------- */
  217.  
  218.   // prepare the output
  219.   AVCodec *pOCodec = avcodec_find_encoder(CODEC_ID_PNG);
  220.  
  221.   /* Allocate Output Codec */
  222.   AVCodecContext *pOCodecCtx = avcodec_alloc_context3(pOCodec);
  223.   if (!pOCodecCtx) {
  224.       fprintf(stderr, "Could not allocate codec\n");
  225.       return 1;
  226.   }
  227.  
  228.   /* Initialize picture size and other format parameters */
  229.   pOCodecCtx->width = pICodecCtx->width/2;
  230.   pOCodecCtx->height = pICodecCtx->height/2;
  231.   pOCodecCtx->pix_fmt = PIX_FMT_RGB24;
  232.   pOCodecCtx->time_base.num = 1;
  233.   pOCodecCtx->time_base.den = 1;
  234.   pOCodecCtx->thread_count = 2;
  235.  
  236.   if (avcodec_open2(pOCodecCtx, pOCodec,NULL) < 0) {
  237.       fprintf(stderr, "Could not open final codec\n");
  238.       return 1;
  239.   }
  240.  
  241.   /* -------------------------------------------------------------------------------------- */
  242.  
  243.   finalFrame->pts = 1;
  244.  
  245.   /* -------------------------------------------------------------------------------------- */
  246.  
  247.   // where the encoded frame will be stored
  248.   AVPacket packet;
  249.   av_init_packet(&packet);
  250.   packet.size = szBuffer;
  251.   packet.data = pBuffer;
  252.  
  253.   int gotPacket = 0;
  254.  
  255.   int szBufferActual = avcodec_encode_video2(pOCodecCtx, &packet,pFrame,&gotPacket);
  256.  
  257.   if (!szBufferActual && gotPacket && pOCodecCtx->coded_frame) {
  258.       pOCodecCtx->coded_frame->pts       = packet.pts;
  259.       pOCodecCtx->coded_frame->key_frame = !!(packet.flags & AV_PKT_FLAG_KEY);
  260.   }  
  261.  
  262.   /* Write frame to file */
  263.   FILE *file = fopen("test.png", "wb");
  264.   bRet = fwrite(pBuffer, sizeof(uint8_t), packet.size, file);
  265.   fclose(file);
  266.   if (bRet != packet.size) {
  267.       fprintf(stderr, "Error writing final file\n");
  268.       return 1;
  269.   }
  270.  
  271.   printf("test.png written...\n");
  272.  
  273.   avfilter_unref_buffer(picref);
  274.  
  275.   /* Cleanup */
  276.   if (pBuffer) {
  277.       av_freep(&pBuffer);
  278.       pBuffer = NULL;
  279.       szBuffer = 0;
  280.   }
  281.  
  282.   if (pFrame) {
  283.       av_freep(&pFrame);
  284.       pFrame = NULL;
  285.   }
  286.  
  287.   if (pICodecCtx) {
  288.       avcodec_close(pICodecCtx);
  289.       pICodecCtx = NULL;
  290.   }
  291.  
  292.   if (pOCodecCtx) {
  293.       avcodec_close(pOCodecCtx);
  294.       pOCodecCtx = NULL;
  295.   }
  296.  
  297.   if (pIFormatCtx) {
  298.       avformat_close_input(&pIFormatCtx);
  299.       pIFormatCtx = NULL;
  300.   }
  301.  
  302.   return 0;
  303. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement