Advertisement
zergon321

ffmpeg (libav) basics

Aug 24th, 2021
1,253
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.39 KB | None | 0 0
  1. #include <libavcodec/avcodec.h>
  2. #include <libavformat/avformat.h>
  3. #include <libavutil/avconfig.h>
  4. #include <libswscale/swscale.h>
  5. #include <stdio.h>
  6. #include <stdarg.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <inttypes.h>
  10.  
  11. typedef struct SwsContext SwsContext;
  12.  
  13. static void save_gray_frame(unsigned char *buf, int wrap, int xsize, int ysize, char *filename)
  14. {
  15.     FILE *f;
  16.     int i;
  17.     f = fopen(filename,"w");
  18.     // writing the minimal required header for a pgm file format
  19.     // portable graymap format -> https://en.wikipedia.org/wiki/Netpbm_format#PGM_example
  20.     fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
  21.  
  22.     // writing line by line
  23.     for (i = 0; i < ysize; i++)
  24.         fwrite(buf + i * wrap, 1, xsize, f);
  25.     fclose(f);
  26. }
  27.  
  28. int main() {
  29.     AVFormatContext* ctx = avformat_alloc_context();
  30.  
  31.     if (!ctx) {
  32.         puts("couldn't allocate the context\n");
  33.         return -1;
  34.     }
  35.  
  36.     int res = avformat_open_input(&ctx, "demo.mp4", NULL, NULL);
  37.  
  38.     if (res < 0) {
  39.         puts("couldn't open the media file\n");
  40.         return -1;
  41.     }
  42.  
  43.     printf("Format: %s\n", ctx->iformat->name);
  44.     printf("Format long: %s\n", ctx->iformat->long_name);
  45.     printf("Format MIME type: %s\n", ctx->iformat->mime_type);
  46.     printf("Duration: %lld\n", ctx->duration);
  47.     printf("Bitrate: %lld\n", ctx->bit_rate == 0 ? -1 : ctx->bit_rate);
  48.     printf("Number of streams: %d\n", ctx->nb_streams);
  49.  
  50.     res = avformat_find_stream_info(ctx, NULL);
  51.  
  52.     if (res < 0) {
  53.         puts("couldn't find stream info\n");
  54.         return -1;
  55.     }
  56.  
  57.     putc('\n', stdout);
  58.  
  59.     AVCodec* videoCodec = NULL;
  60.     AVCodecParameters* videoCodecParams = NULL;
  61.     int videoStreamInd = -1;
  62.  
  63.     // Loop through all the streams.
  64.     for (int i = 0; i < ctx->nb_streams; i++) {
  65.         AVStream* stream = ctx->streams[i];
  66.         AVCodecParameters* codecParams = stream->codecpar;
  67.  
  68.         switch (codecParams->codec_type)
  69.         {
  70.         case AVMEDIA_TYPE_VIDEO:
  71.             puts("Type: video");
  72.             printf("Resolution: %dx%d\n", codecParams->width, codecParams->height);
  73.             break;
  74.  
  75.         case AVMEDIA_TYPE_AUDIO:
  76.             puts("Type: audio");
  77.             printf("Number of channels: %d\n", codecParams->channels);
  78.             printf("Sample rate: %d\n", codecParams->sample_rate);
  79.             printf("Frame size: %d\n", codecParams->frame_size);
  80.             break;
  81.        
  82.         default:
  83.             printf("unsupported stream type: %d\n", codecParams->codec_type);
  84.             return -1;
  85.         }
  86.  
  87.         printf("Stream %d index: %d\n", i, stream->index);
  88.         printf("Stream %d time base before opened: %d/%d\n", i, stream->time_base.num, stream->time_base.den);
  89.         printf("Stream %d frame rate before opened: %d/%d\n", i, stream->r_frame_rate.num, stream->r_frame_rate.den);
  90.         printf("Stream %d start time: %d\n", i, stream->start_time);
  91.         printf("Stream %d duration: %d\n", i, stream->duration);
  92.         printf("Stream %d number of frames: %d\n", i, stream->nb_frames);
  93.         printf("Stream %d bit rate: %d\n", i, codecParams->bit_rate);
  94.  
  95.         AVCodec* codec = avcodec_find_decoder(codecParams->codec_id);
  96.  
  97.         if (codec == NULL) {
  98.             printf("couldn't find the codec with ID = %d", codecParams->codec_id);
  99.             return -1;
  100.         }
  101.  
  102.         printf("Stream %d codec name: %s\n", i, codec->name);
  103.         printf("Stream %d codec long name: %s\n", i, codec->long_name);
  104.         putc('\n', stdout);
  105.  
  106.         if (codecParams->codec_type == AVMEDIA_TYPE_VIDEO) {
  107.             videoStreamInd = i;
  108.             videoCodec = codec;
  109.             videoCodecParams = codecParams;
  110.         }
  111.     }
  112.  
  113.     AVCodecContext* videoCtx = avcodec_alloc_context3(videoCodec);
  114.  
  115.     if (videoCtx == NULL) {
  116.         puts("couldn't allocate a codec context");
  117.         return -1;
  118.     }
  119.  
  120.     res = avcodec_parameters_to_context(videoCtx, videoCodecParams);
  121.  
  122.     if (res < 0) {
  123.         puts("couldn't send codec parameters to the codec context");
  124.         return -1;
  125.     }
  126.  
  127.     res = avcodec_open2(videoCtx, videoCodec, NULL);
  128.  
  129.     if (res < 0) {
  130.         puts("couldn't open the codec context");
  131.         return -1;
  132.     }
  133.  
  134.     AVPacket* packet = av_packet_alloc();
  135.  
  136.     if (packet == NULL) {
  137.         puts("couldn't allocate a packet");
  138.         return -1;
  139.     }
  140.  
  141.     AVFrame* frame = av_frame_alloc();
  142.  
  143.     if (frame == NULL) {
  144.         puts("couldn't allocate a frame");
  145.         return -1;
  146.     }
  147.  
  148.     AVFrame* rgbaFrame = av_frame_alloc();
  149.  
  150.     if (frame == NULL) {
  151.         puts("couldn't allocate an RGBA frame");
  152.         return -1;
  153.     }
  154.  
  155.     int size = avpicture_get_size(AV_PIX_FMT_RGBA, videoCtx->width, videoCtx->height);
  156.     uint8_t* buf = (uint8_t*)av_malloc(size * sizeof(uint8_t));
  157.     avpicture_fill((AVPicture*)rgbaFrame, buf, AV_PIX_FMT_RGBA, videoCtx->width, videoCtx->height);
  158.     SwsContext* swsCtx = sws_getContext(videoCtx->width, videoCtx->height, videoCtx->pix_fmt,
  159.         videoCtx->width, videoCtx->height, AV_PIX_FMT_RGBA, SWS_BICUBIC, NULL, NULL, NULL);
  160.  
  161.     int i = 0;
  162.  
  163.     while (av_read_frame(ctx, packet) >= 0)
  164.     {
  165.         if (packet->stream_index != videoStreamInd) {
  166.             continue;
  167.         }
  168.  
  169.         res = avcodec_send_packet(videoCtx, packet);
  170.  
  171.         if (res < 0) {
  172.             printf("couldn't send the packet to the decoder %d\n", res);
  173.             continue;
  174.         }
  175.  
  176.         res = avcodec_receive_frame(videoCtx, frame);
  177.  
  178.         if (res < 0) {
  179.             puts("couldn't receive the frame from the decoder\n");
  180.             continue;
  181.         }
  182.  
  183.         printf(
  184.             "Frame %c (%d) pts %d dts %d key_frame %d [coded_picture_number %d, display_picture_number %d]\n",
  185.             av_get_picture_type_char(frame->pict_type),
  186.             videoCtx->frame_number,
  187.             frame->pts,
  188.             frame->pkt_dts,
  189.             frame->key_frame,
  190.             frame->coded_picture_number,
  191.             frame->display_picture_number
  192.         );
  193.  
  194.         // Transcode to RGBA.
  195.         sws_scale(swsCtx, frame->data, frame->linesize, 0, videoCtx->height, rgbaFrame->data, rgbaFrame->linesize);
  196.  
  197.         char buffer[32];
  198.         sprintf(buffer, "frame_%d.pgm", i);
  199.         save_gray_frame(frame->data[0], frame->linesize[0], frame->width, frame->height, buffer);
  200.  
  201.         i++;
  202.  
  203.         if (i == 7) {
  204.             break;
  205.         }
  206.     }
  207.  
  208.     return 0;
  209. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement