Advertisement
Guest User

Untitled

a guest
Apr 30th, 2018
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.05 KB | None | 0 0
  1. #include <libavfilter/avfilter.h>
  2. #include <libavfilter/buffersink.h>
  3. #include <libavfilter/buffersrc.h>
  4. #include <libavutil/frame.h>
  5. #include <libavutil/opt.h>
  6. #include <libavutil/pixdesc.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9.  
  10. static const enum AVPixelFormat format = AV_PIX_FMT_YUV420P;
  11. static const int height = 240;
  12. static const int width = 320;
  13. static const int new_height = 100;
  14. static const int new_width = 200;
  15.  
  16. static AVFilterContext *buffersrc_ctx, *buffersink_ctx;
  17. static AVFilterGraph *graph;
  18. static AVFilterInOut *outputs, *inputs;
  19.  
  20. static void save_yuv_frame(AVFrame *frame, int frame_number)
  21. {
  22.     char filename[32];
  23.     snprintf(filename, sizeof(filename), "frame%0d.yuv", frame_number);
  24.     FILE *file = fopen(filename, "wb");
  25.  
  26.     uint32_t pitch_y = frame->linesize[0];
  27.     uint32_t pitch_u = frame->linesize[1];
  28.     uint32_t pitch_v = frame->linesize[2];
  29.  
  30.     uint8_t *y = frame->data[0];
  31.     uint8_t *u = frame->data[1];
  32.     uint8_t *v = frame->data[2];
  33.  
  34.     for (uint32_t i = 0; i < (uint32_t)frame->height; i++) {
  35.         fwrite(y, frame->width, 1, file);
  36.         y += pitch_y;
  37.     }
  38.  
  39.     for (uint32_t i = 0; i < (uint32_t)frame->height/2; i++) {
  40.         fwrite(u, frame->width/2, 1, file);
  41.         u += pitch_u;
  42.     }
  43.  
  44.     for (uint32_t i = 0; i < (uint32_t)frame->height/2; i++) {
  45.         fwrite(v, frame->width/2, 1, file);
  46.         v += pitch_v;
  47.     }
  48.  
  49.     fclose(file);
  50. }
  51.  
  52. static void fill_yuv_frame(AVFrame *frame, int frame_index, int width, int height)
  53. {
  54.     for (int y = 0; y < height; y++)
  55.         for (int x = 0; x < width; x++)
  56.             frame->data[0][y * frame->linesize[0] + x] = x + y + frame_index * 3;
  57.  
  58.     for (int y = 0; y < height / 2; y++) {
  59.         for (int x = 0; x < width / 2; x++) {
  60.             frame->data[1][y * frame->linesize[1] + x] = 128 + y + frame_index * 2;
  61.             frame->data[2][y * frame->linesize[2] + x] = 64 + x + frame_index * 5;
  62.         }
  63.     }
  64. }
  65.  
  66. static int init_filters(const char *spec)
  67. {
  68.     int ret = 0;
  69.  
  70.     outputs = avfilter_inout_alloc();
  71.     inputs = avfilter_inout_alloc();
  72.     graph = avfilter_graph_alloc();
  73.  
  74.     if (!outputs || !inputs || !graph) {
  75.         printf("Failed to allocate filter chain\n");
  76.         goto end;
  77.     }
  78.  
  79.     char args[512];
  80.     snprintf(args, sizeof(args),
  81.              "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
  82.              width, height, format, 1, 1, 1, 1);
  83.  
  84.     const AVFilter* buffersrc = avfilter_get_by_name("buffer");
  85.     const AVFilter* buffersink = avfilter_get_by_name("buffersink");
  86.  
  87.     if ((ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
  88.             args, NULL, graph)) < 0) {
  89.         printf("Failed to create buffer source filter: %s\n", av_err2str(ret));
  90.         goto end;
  91.     }
  92.  
  93.     if ((ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
  94.             NULL, NULL, graph)) < 0) {
  95.         printf("Failed to create buffer sink filter: %s\n", av_err2str(ret));
  96.         goto end;
  97.     }
  98.  
  99.     enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE };
  100.     if ((ret = av_opt_set_int_list(buffersink_ctx, "pix_fmts", pix_fmts,
  101.                                    AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN)) < 0) {
  102.         printf("Failed to set pixel formats: %s\n", av_err2str(ret));
  103.         goto end;
  104.     }
  105.  
  106.     outputs->name = av_strdup("in");
  107.     outputs->filter_ctx = buffersrc_ctx;
  108.     outputs->pad_idx = 0;
  109.     outputs->next = NULL;
  110.  
  111.     inputs->name = av_strdup("out");
  112.     inputs->filter_ctx = buffersink_ctx;
  113.     inputs->pad_idx = 0;
  114.     inputs->next = NULL;
  115.  
  116.     if ((ret = avfilter_graph_parse_ptr(graph, spec, &inputs, &outputs, NULL)) < 0) {
  117.         printf("Could not parse filter chain '%s': %s\n", spec, av_err2str(ret));
  118.         goto end;
  119.     }
  120.  
  121.     if ((ret = avfilter_graph_config(graph, NULL)) < 0) {
  122.         printf("Failed to configure graph: %s\n", av_err2str(ret));
  123.         goto end;
  124.     }
  125.  
  126. end:
  127.     return ret;
  128. }
  129.  
  130. static int apply_filters(AVFrame *frame)
  131. {
  132.     int ret = 0;
  133.     AVFrame* filtered = NULL;
  134.  
  135.     if ((ret = av_buffersrc_add_frame_flags(buffersrc_ctx, frame, 0)) < 0) {
  136.         printf("Error feeding filter chain: %s\n", av_err2str(ret));
  137.         goto end;
  138.     }
  139.  
  140.     while (ret >= 0) {
  141.         filtered = av_frame_alloc();
  142.         if (!filtered) {
  143.             ret = AVERROR(ENOMEM);
  144.             break;
  145.         }
  146.  
  147.         if ((ret = av_buffersink_get_frame(buffersink_ctx, filtered)) < 0) {
  148.             // not an error
  149.             if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
  150.                 ret = 0;
  151.  
  152.             av_frame_free(&filtered);
  153.             break;
  154.         }
  155.  
  156.         // move filtered frame into frame, so caller can access it
  157.         av_frame_unref(frame);
  158.         av_frame_move_ref(frame, filtered);
  159.         av_frame_free(&filtered);
  160.     }
  161. end:
  162.     return ret;
  163. }
  164.  
  165. int main(int argc, char *argv[])
  166. {
  167.     int ret = 0;
  168.  
  169.     if (argc > 1 && argv[1]) {
  170.         int level = atoi(argv[1]);
  171.         av_log_set_level(level);
  172.     }
  173.  
  174.     AVFrame* frame = NULL;
  175.     for (int i = 0; i < 5; ++i) {
  176.         frame = av_frame_alloc();
  177.         frame->format = AV_PIX_FMT_YUV420P;
  178.         frame->width = width;
  179.         frame->height = height;
  180.         if ((ret = av_frame_get_buffer(frame, 32)) < 0) {
  181.             printf("Failed to allocate frame buffer: %s\n", av_err2str(ret));
  182.             goto end;
  183.         }
  184.         fill_yuv_frame(frame, i, width, height);
  185.  
  186.         char spec[128];
  187.         snprintf(spec, sizeof(spec), "scale=w=%d:h=%d:dst_format=%d", new_width, new_height, AV_PIX_FMT_YUV420P);
  188.         if ((ret = init_filters(spec)) < 0)
  189.             goto end;
  190.  
  191.         if ((ret = apply_filters(frame)) < 0)
  192.             goto end;
  193.  
  194.         printf("Frame scaled from %dx%d to %dx%d\n", width, height, frame->width, frame->height);
  195.  
  196.         save_yuv_frame(frame, i);
  197.  
  198.         av_frame_free(&frame);
  199.     }
  200.  
  201. end:
  202.     av_frame_free(&frame);
  203.     avfilter_inout_free(&outputs);
  204.     avfilter_inout_free(&inputs);
  205.     avfilter_graph_free(&graph);
  206.  
  207.     return ret;
  208. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement