rexim преди 6 години
родител
ревизия
cfebf8f6ee
променени са 4 файла, в които са добавени 135 реда и са изтрити 10 реда
  1. 2 1
      TODO.org
  2. 2 1
      libavcodec-cairo-probe/.gitignore
  3. 2 2
      libavcodec-cairo-probe/Makefile
  4. 129 6
      libavcodec-cairo-probe/main.c

+ 2 - 1
TODO.org

@@ -33,4 +33,5 @@
     - [X] [[https://www.ffmpeg.org/doxygen/0.6/api-example_8c-source.html][FFmpeg: libavcodec/api-example.c Source File]]
     - [X] [[https://www.ffmpeg.org/doxygen/0.6/api-example_8c-source.html][FFmpeg: libavcodec/api-example.c Source File]]
       - [X] Does not work on my version of ffmpeg 3.4+
       - [X] Does not work on my version of ffmpeg 3.4+
     - [ ] [[https://www.ffmpeg.org/doxygen/3.4/encode_video_8c-example.html][FFmpeg: encode_video.c]]
     - [ ] [[https://www.ffmpeg.org/doxygen/3.4/encode_video_8c-example.html][FFmpeg: encode_video.c]]
-      - [ ] 
+      - [ ] Example works well
+        - [ ] Now we need to integrate with cairo

+ 2 - 1
libavcodec-cairo-probe/.gitignore

@@ -1 +1,2 @@
-avcodec-probe
+avcodec-probe
+*.mpg

+ 2 - 2
libavcodec-cairo-probe/Makefile

@@ -1,7 +1,7 @@
 LIBS=cairo sdl2 libavcodec
 LIBS=cairo sdl2 libavcodec
 
 
-hello.png: avcodec-probe
-	./avcodec-probe
+hello.mpg: avcodec-probe
+	./avcodec-probe hello.mpg mpeg1video
 
 
 avcodec-probe: main.c
 avcodec-probe: main.c
 	gcc -Wall -Werror $(shell pkg-config --cflags $(LIBS)) \
 	gcc -Wall -Werror $(shell pkg-config --cflags $(LIBS)) \

+ 129 - 6
libavcodec-cairo-probe/main.c

@@ -2,16 +2,139 @@
 
 
 #include <cairo.h>
 #include <cairo.h>
 #include <libavcodec/avcodec.h>
 #include <libavcodec/avcodec.h>
+#include <libavutil/opt.h>
+
+static void encode(AVCodecContext *context, AVFrame *frame,
+                   AVPacket *pkt, FILE *outfile)
+{
+    if (frame) {
+        printf("Send frame %3"PRId64"\n", frame->pts);
+    }
+
+    int ret = avcodec_send_frame(context, frame);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending a frame for encoding: %s\n",
+                av_err2str(ret));
+        exit(EXIT_FAILURE);
+    }
+
+    while (ret >= 0) {
+        ret = avcodec_receive_packet(context, pkt);
+        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
+            return;
+        } else if (ret < 0) {
+            fprintf(stderr, "Error during encoding\n");
+            exit(EXIT_FAILURE);
+        }
+
+        printf("Write packet %3"PRId64" (size=%5d)\n",
+               pkt->pts, pkt->size);
+        fwrite(pkt->data, 1, pkt->size, outfile);
+        av_packet_unref(pkt);
+    }
+}
 
 
 int main(int argc, char *argv[])
 int main(int argc, char *argv[])
 {
 {
-    AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO);
-    if (!codec) {
-        fprintf(stderr, "codec not found\n");
-        return -1;
+    if (argc <= 2) {
+        fprintf(stderr, "Usage: %s <output-file> <codec-name>\n", argv[0]);
+        exit(EXIT_FAILURE);
     }
     }
 
 
-    AVCodecContext *c = avcodec_alloc_context();
+    const char *filename = argv[1];
+    const char *codec_name = argv[2];
+
+    const AVCodec *codec = avcodec_find_encoder_by_name(codec_name);
+    if (codec == NULL) {
+        fprintf(stderr, "Codec '%s' not found\n", codec_name);
+        exit(EXIT_FAILURE);
+    }
+
+    AVCodecContext *context = avcodec_alloc_context3(codec);
+    if (context == NULL) {
+        fprintf(stderr, "Could not allocate video codec context\n");
+        exit(EXIT_FAILURE);
+    }
+    context->bit_rate = 400 * 1000;
+    context->width = 352;
+    context->height = 288;
+    context->time_base = (AVRational){1, 25};
+    context->framerate = (AVRational){25, 1};
+    context->gop_size = 10;
+    context->max_b_frames = 1;
+    context->pix_fmt = AV_PIX_FMT_YUV420P;
+
+    AVPacket *pkt = av_packet_alloc();
+    if (!pkt) {
+        fprintf(stderr, "Could not allocate AVPacket\n");
+        exit(EXIT_FAILURE);
+    }
+
+    if (codec->id == AV_CODEC_ID_H264) {
+        av_opt_set(context->priv_data, "preset", "slow", 0);
+    }
+
+    int ret = avcodec_open2(context, codec, NULL);
+    if (ret < 0) {
+        fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
+        exit(EXIT_FAILURE);
+    }
+
+    FILE *f = fopen(filename, "wb");
+    if (!f) {
+        fprintf(stderr, "Could not open %s\n", filename);
+        exit(EXIT_FAILURE);
+    }
+
+    AVFrame *frame = av_frame_alloc();
+    if (!frame) {
+        fprintf(stderr, "Could not allocate video frame\n");
+        exit(EXIT_FAILURE);
+    }
+    frame->format = context->pix_fmt;
+    frame->width  = context->width;
+    frame->height = context->height;
+
+    ret = av_frame_get_buffer(frame, 32);
+    if (ret < 0) {
+        fprintf(stderr, "Could not allocate the video frame data: %s\n",
+                av_err2str(ret));
+        exit(EXIT_FAILURE);
+    }
+
+    for (int i = 0; i < 25; i++) {
+        ret = av_frame_make_writable(frame);
+        if (ret < 0) {
+            fprintf(stderr, "%s\n", av_err2str(ret));
+            exit(EXIT_FAILURE);
+        }
+
+        for (int y = 0; y < context->height; ++y) {
+            for (int x = 0; x < context->width; ++x) {
+                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
+            }
+        }
+
+        for (int y = 0; y < context->height / 2; ++y) {
+            for (int x = 0; x < context->width / 2; ++x) {
+                frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
+                frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
+            }
+        }
+
+        frame->pts = i;
+
+        encode(context, frame, pkt, f);
+    }
+    encode(context, NULL, pkt, f);
+
+    uint8_t endcode[] = {0, 0, 1, 0xb7};
+    fwrite(endcode, 1, sizeof(endcode), f);
+
+    fclose(f);
+    avcodec_free_context(&context);
+    av_frame_free(&frame);
+    av_packet_free(&pkt);
 
 
-    return 0;
+    return EXIT_SUCCESS;
 }
 }