This is an automated email from the git hooks/post-receive script.

git pushed a commit to branch main
in repository efl_ffmpeg.

View the commit online.

commit 6ac46273bb961867eec184ea67922676f39d2118
Author: Vincent Torri <vto...@outlook.fr>
AuthorDate: Fri Jun 30 22:43:12 2023 +0200

    add files
---
 ffmpeg.c | 375 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ffmpeg.h |  71 ++++++++++++
 main.c   | 299 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 745 insertions(+)

diff --git a/ffmpeg.c b/ffmpeg.c
new file mode 100644
index 0000000..55ed105
--- /dev/null
+++ b/ffmpeg.c
@@ -0,0 +1,375 @@
+
+#include <Eina.h>
+
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+
+#include "ffmpeg.h"
+
+FFmpeg *
+ff_new(void)
+{
+    FFmpeg *ff;
+
+    ff = (FFmpeg*)calloc(1, sizeof(FFmpeg));
+    if (!ff)
+        return NULL;
+
+    ff->videos = eina_array_new(1);
+    if (!ff->videos)
+        goto free_ff;
+
+    ff->audios = eina_array_new(1);
+    if (!ff->audios)
+        goto free_videos;
+
+    return ff;
+
+  free_videos:
+    eina_array_free(ff->videos);
+  free_ff:
+    free(ff);
+
+    return NULL;
+}
+
+void
+ff_free(FFmpeg *ff)
+{
+    if (!ff)
+        return;
+
+    eina_array_free(ff->audios);
+    eina_array_free(ff->videos);
+    free(ff);
+}
+
+static void
+_ff_free_lists(FFmpeg *ff)
+{
+    Eina_Array_Iterator iterator;
+    void *p;
+    unsigned int i;
+
+    EINA_ARRAY_ITER_NEXT(ff->audios, i, p, iterator)
+    {
+        free(p);
+    }
+    eina_array_free(ff->audios);
+
+    EINA_ARRAY_ITER_NEXT(ff->videos, i, p, iterator)
+    {
+        free(p);
+    }
+    eina_array_free(ff->videos);
+}
+
+int
+ff_file_open(FFmpeg *ff, const char *file)
+{
+    FF_Video *video;
+    int err;
+    unsigned int i;
+
+    if ((!file || !*file))
+        return 0;
+
+    ff->format_ctx = avformat_alloc_context();
+    if (!ff->format_ctx)
+    {
+        printf("ff NULL\n");
+        return 0;
+    }
+
+    ff->video_index = -1;
+    ff->audio_index = -1;
+
+    /* parse header of the file */
+    err = avformat_open_input(&ff->format_ctx, file, NULL, NULL);
+    if (err)
+    {
+        printf("avformat_open_input() failed");
+        goto free_format_ctx;
+    }
+
+    /* fill format_stx->streams */
+    if (avformat_find_stream_info(ff->format_ctx, NULL) < 0)
+    {
+        printf("avformat_find_stream_info() failed");
+        goto free_format_ctx;
+    }
+
+    printf(" * file name   : %s\n", ff->format_ctx->url);
+    printf(" * format name : %s\n", ff->format_ctx->iformat->name);
+    printf(" * duration    : %lld\n", ff->format_ctx->duration);
+    printf(" * bitrate     : %lld\n", ff->format_ctx->bit_rate);
+
+    for (i = 0; i < ff->format_ctx->nb_streams; i++)
+    {
+        const AVCodecParameters *codec_par;
+        const AVCodec *codec;
+
+        printf(" * stream %d time base : %d/%d\n",
+               i,
+               ff->format_ctx->streams[i]->time_base.num,
+               ff->format_ctx->streams[i]->time_base.den);
+        printf(" * stream %d r frame rate: %d/%d\n",
+               i,
+               ff->format_ctx->streams[i]->r_frame_rate.num,
+               ff->format_ctx->streams[i]->r_frame_rate.den);
+        printf(" * stream %d a frame rate: %d/%d\n",
+               i,
+               ff->format_ctx->streams[i]->avg_frame_rate.num,
+               ff->format_ctx->streams[i]->avg_frame_rate.den);
+        printf(" * stream %d start time: %lld\n",
+               i,
+               ff->format_ctx->streams[i]->start_time);
+        printf(" * stream %d duration  : %lld\n",
+               i,
+               ff->format_ctx->streams[i]->duration);
+        printf(" * stream %d nb frames : %lld\n",
+               i,
+               ff->format_ctx->streams[i]->nb_frames);
+
+        codec_par = ff->format_ctx->streams[i]->codecpar;
+        codec = avcodec_find_decoder(codec_par->codec_id);
+
+        if (!codec)
+        {
+            printf("unsupported codec, continuing\n");
+            continue;
+        }
+
+        if (codec_par->codec_type == AVMEDIA_TYPE_VIDEO)
+        {
+            video = (FF_Video *)calloc(1, sizeof(FF_Video));
+            if (!video)
+            {
+                printf("fail to allocate memory for video\n");
+                continue;
+            }
+
+            video->codec_par = codec_par;
+            video->codec = codec;
+            video->stream_index = i;
+            eina_array_push(ff->videos, video);
+
+            if (ff->video_index == -1)
+            {
+                ff->video_index = 0;
+            }
+        }
+        else if (codec_par->codec_type == AVMEDIA_TYPE_AUDIO)
+        {
+            FF_Audio *audio;
+
+            audio = (FF_Audio *)calloc(1, sizeof(FF_Audio));
+            if (!audio)
+            {
+                printf("fail to allocate memory for audio\n");
+                continue;
+            }
+
+            audio->codec_par = codec_par;
+            audio->codec = codec;
+            audio->stream_index = i;
+            eina_array_push(ff->audios, audio);
+
+            if (ff->audio_index == -1)
+            {
+                ff->audio_index = 0;
+            }
+        }
+    }
+
+    if (ff->video_index == -1)
+    {
+        printf("WARNING : no video stream`n");
+    }
+
+    video = (FF_Video *)eina_array_data_get(ff->videos, ff->video_index);
+    ff->codec_ctx = avcodec_alloc_context3(video->codec);
+    if (!ff->codec_ctx)
+    {
+        goto free_eina_lists;
+    }
+
+    if (avcodec_parameters_to_context(ff->codec_ctx, video->codec_par) < 0)
+    {
+        printf("WARNING : no video stream`n");
+        goto free_codec_ctx;
+    }
+
+    if (avcodec_open2(ff->codec_ctx, video->codec, NULL) < 0)
+    {
+        printf("failed to open codec through avcodec_open2\n");
+        goto free_codec_ctx;
+    }
+
+    return 1;
+
+  free_codec_ctx:
+    avcodec_free_context(&ff->codec_ctx);
+  free_eina_lists:
+    _ff_free_lists(ff);
+  free_format_ctx:
+    avformat_free_context(ff->format_ctx);
+    ff->audio_index = -1;
+    ff->video_index = -1;
+
+    return 0;
+}
+
+void
+ff_file_close(FFmpeg *ff)
+{
+    avcodec_free_context(&ff->codec_ctx);
+    _ff_free_lists(ff);
+    avformat_free_context(ff->format_ctx);
+    ff->audio_index = -1;
+    ff->video_index = -1;
+}
+
+void
+ff_size_get(FFmpeg *ff, int *width, int *height)
+{
+    FF_Video *v;
+
+    if (width) *width = 0;
+    if (height) *height = 0;
+    if (ff->video_index < 0)
+        return;
+
+    v = (FF_Video *)eina_array_data_get(ff->videos, ff->video_index);
+
+    if (width)
+    {
+        *width = ff->format_ctx->streams[v->stream_index]->codecpar->width;
+    }
+
+    if (height)
+    {
+        *height = ff->format_ctx->streams[v->stream_index]->codecpar->height;
+    }
+}
+
+double
+ff_len_get(FFmpeg *ff)
+{
+    /*
+     * get duration of the file, not of the video stream
+     * see https://stackoverflow.com/a/32538549
+     */
+    return ff->format_ctx->duration / (double)AV_TIME_BASE;
+}
+
+int
+_ff_fps_get(FFmpeg *ff, int *n, int *d)
+{
+    FF_Video *v;
+
+    if (n) *n = 0;
+    if (d) *d = 0;
+    if (ff->video_index < 0)
+        return 0;
+
+    v = (FF_Video *)eina_array_data_get(ff->videos, ff->video_index);
+
+    if (n)
+        *n = ff->format_ctx->streams[v->stream_index]->avg_frame_rate.num;
+
+    if (d)
+        *d = ff->format_ctx->streams[v->stream_index]->avg_frame_rate.den;
+
+    return 1;
+}
+
+int
+ff_fps_num_get(FFmpeg *ff)
+{
+    int num;
+
+    _ff_fps_get(ff, &num, NULL);
+
+    return num;
+}
+
+int
+ff_fps_den_get(FFmpeg *ff)
+{
+    int den;
+
+    _ff_fps_get(ff, NULL, &den);
+
+    return den;
+}
+
+double
+ff_fps_get(FFmpeg *ff)
+{
+    int num, den;
+
+    if (!_ff_fps_get(ff, &num, &den))
+        return 0.0;
+
+    return (double)num / (double)den;
+}
+
+int
+ff_video_handled(FFmpeg *ff)
+{
+    return ff->video_index >= 0;
+}
+
+int
+ff_audio_handled(FFmpeg *ff)
+{
+    return ff->audio_index >= 0;
+}
+
+int
+ff_format_get(FFmpeg *ff)
+{
+}
+
+int
+ff_video_channel_count(FFmpeg *ff)
+{
+    return eina_array_count_get(ff->videos);
+}
+
+void
+ff_video_channel_set(FFmpeg *ff, int channel)
+{
+    if ((channel >= 0) || (channel < ff_video_channel_count(ff)))
+    {
+        ff->video_index = channel;
+    }
+}
+
+int
+ff_video_channel_get(FFmpeg *ff)
+{
+    return ff->video_index;
+}
+
+int
+ff_audio_channel_count(FFmpeg *ff)
+{
+    return eina_array_count_get(ff->audios);
+}
+
+void
+ff_audio_channel_set(FFmpeg *ff, int channel)
+{
+    if ((channel >= 0) || (channel < ff_audio_channel_count(ff)))
+    {
+        ff->audio_index = channel;
+    }
+}
+
+int
+ff_audio_channel_get(FFmpeg *ff)
+{
+    return ff->audio_index;
+}
diff --git a/ffmpeg.h b/ffmpeg.h
new file mode 100644
index 0000000..fdbb782
--- /dev/null
+++ b/ffmpeg.h
@@ -0,0 +1,71 @@
+#ifndef FFMPEG_H
+#define FFMPEG_H
+
+typedef struct FF_Video FF_Video;
+typedef struct FF_Audio FF_Audio;
+typedef struct FFmpeg FFmpeg;
+
+struct FF_Video
+{
+    const AVCodecParameters *codec_par;
+    const AVCodec *codec;
+    int stream_index;
+};
+
+struct FF_Audio
+{
+    const AVCodecParameters *codec_par;
+    const AVCodec *codec;
+    int stream_index;
+};
+
+struct FFmpeg
+{
+    AVFormatContext *format_ctx;
+    AVCodecContext *codec_ctx;
+    Eina_Array *videos;
+    Eina_Array *audios;
+    int video_index;
+    int audio_index;
+};
+
+
+FFmpeg *ff_new(void);
+
+void ff_free(FFmpeg *ff);
+
+int ff_file_open(FFmpeg *ff, const char *file);
+
+void ff_file_close(FFmpeg *ff);
+
+void ff_size_get(FFmpeg *ff, int *width, int *height);
+
+double ff_len_get(FFmpeg *ff);
+
+int _ff_fps_get(FFmpeg *ff, int *n, int *d);
+
+int ff_fps_num_get(FFmpeg *ff);
+
+int ff_fps_den_get(FFmpeg *ff);
+
+double ff_fps_get(FFmpeg *ff);
+
+int ff_video_handled(FFmpeg *ff);
+
+int ff_audio_handled(FFmpeg *ff);
+
+int ff_format_get(FFmpeg *ff);
+
+int ff_video_channel_count(FFmpeg *ff);
+
+void ff_video_channel_set(FFmpeg *ff, int channel);
+
+int ff_video_channel_get(FFmpeg *ff);
+
+int ff_audio_channel_count(FFmpeg *ff);
+
+void ff_audio_channel_set(FFmpeg *ff, int channel);
+
+int ff_audio_channel_get(FFmpeg *ff);
+
+#endif /* FFMPEG_H */
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..b75f5c2
--- /dev/null
+++ b/main.c
@@ -0,0 +1,299 @@
+/* gcc -g -Wall -Wextra -o ffmpeg main.c ffmpeg.c `pkg-config --cflags --libs ecore-evas libavcodec libavformat libavutil libswscale ecore-evas` */
+
+#include <stdio.h>
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+
+#include <libavcodec/avcodec.h>
+#include <libavformat/avformat.h>
+#include <libswscale/swscale.h>
+
+#include "ffmpeg.h"
+
+typedef struct
+{
+    Evas_Object *img;
+    FFmpeg *ff;
+    AVFrame *frame;
+    AVPacket *packet;
+    struct SwsContext *swscale_ctx;
+    int current_frame;
+} FF_Ctx;
+
+
+void _quit(Ecore_Evas *ee)
+{
+    ecore_main_loop_quit();
+    (void)ee;
+}
+
+void _resize(Ecore_Evas *ee)
+{
+    printf("resize\n");
+    (void)ee;
+}
+
+Eina_Bool
+display_frame_cb(void *data)
+{
+    FF_Ctx *ff_ctx = data;
+    FF_Video *v;
+
+    ff_ctx->current_frame++;
+    printf("NEW : %d\n", ff_ctx->current_frame);
+
+    while (av_read_frame(ff_ctx->ff->format_ctx, ff_ctx->packet) >= 0)
+    {
+        v = eina_array_data_get(ff_ctx->ff->videos, ff_ctx->ff->video_index);
+        if (ff_ctx->packet->stream_index == v->stream_index)
+        {
+            int response;
+
+            response = avcodec_send_packet(ff_ctx->ff->codec_ctx, ff_ctx->packet);
+            if (response < 0)
+                return ECORE_CALLBACK_RENEW;
+            while (response >= 0)
+            {
+                response = avcodec_receive_frame(ff_ctx->ff->codec_ctx, ff_ctx->frame);
+                if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
+                {
+                    break;
+                }
+                else if (response < 0) {
+                    return ECORE_CALLBACK_RENEW;
+                }
+
+                if (response >= 0)
+                {
+                    printf("fame %d: size %d x %d  ptr %p  %p %p stride: %d %d %d\n",
+                           ff_ctx->ff->codec_ctx->frame_number,
+                           ff_ctx->frame->width,
+                           ff_ctx->frame->height,
+                           ff_ctx->frame->data[0],
+                           ff_ctx->frame->data[1],
+                           ff_ctx->frame->data[2],
+                           ff_ctx->frame->linesize[0],
+                           ff_ctx->frame->linesize[1],
+                           ff_ctx->frame->linesize[2]);
+                    evas_object_image_size_set(ff_ctx->img, ff_ctx->frame->width, ff_ctx->frame->height);
+                    evas_object_resize(ff_ctx->img, ff_ctx->frame->width, ff_ctx->frame->height);
+                    if (ff_ctx->frame->format != AV_PIX_FMT_YUV420P)
+                    {
+                        printf("NOOOOOO !");
+                    }
+                    else
+                    {
+                        evas_object_image_alpha_set(ff_ctx->img, 0);
+                        evas_object_image_colorspace_set(ff_ctx->img, EVAS_COLORSPACE_YCBCR422P601_PL);
+                        evas_object_image_size_set(ff_ctx->img, ff_ctx->frame->width, ff_ctx->frame->height);
+                        evas_object_resize(ff_ctx->img, ff_ctx->frame->width, ff_ctx->frame->height);
+                        unsigned char *iter_src;
+                        unsigned char **data;
+                        unsigned char **iter_dst;
+                        int i;
+
+                        data = "" 1);
+                        if (!data)
+                            printf("arg NO NO\n");
+                        iter_src = ff_ctx->frame->data[0];
+                        iter_dst = data;
+                        for (i = 0; i < ff_ctx->frame->height; i++)
+                        {
+                            printf(" i == %d\n", i);
+                            *iter_dst = NULL;
+                            *iter_dst = iter_src;
+                            iter_dst++;
+                            iter_src += ff_ctx->frame->linesize[0];
+                            printf(" **** %d\n", (int)(iter_src - ff_ctx->frame->data[0]));
+                        }
+
+                        iter_src = ff_ctx->frame->data[1];
+                        for (i = 0; i < ff_ctx->frame->height / 2; i++)
+                        {
+                            *iter_dst = iter_src;
+                            iter_dst++;
+                            iter_src += ff_ctx->frame->linesize[1];
+                        }
+
+                        iter_src = ff_ctx->frame->data[2];
+                        for (i = 0; i < ff_ctx->frame->height / 2; i++)
+                        {
+                            *iter_dst = iter_src;
+                            iter_dst++;
+                            iter_src += ff_ctx->frame->linesize[2];
+                        }
+                        /* unsigned char *out_data[8] = { data, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; */
+                        /* int out_line[8] = { ff_ctx->frame->width * 4, 0, 0, 0, 0, 0, 0, 0 }; */
+                        /* sws_scale(ff_ctx->swscale_ctx, */
+                        /*           (const uint8_t * const *)ff_ctx->frame->data, */
+                        /*           (const int *)ff_ctx->frame->linesize, */
+                        /*           0, ff_ctx->frame->height, */
+                        /*           out_data, out_line); */
+                        //unsigned char data = "" ff_ctx->frame->data[0]);
+                        evas_object_image_data_set(ff_ctx->img, data);
+                        evas_object_image_data_update_add(ff_ctx->img,
+                                                          0, 0,
+                                                          ff_ctx->frame->width,
+                                                          ff_ctx->frame->height);
+                        evas_object_image_pixels_dirty_set(ff_ctx->img, 0);
+                    }
+                    return ECORE_CALLBACK_RENEW;
+                }
+            }
+        }
+    }
+
+#if 0
+    if (av_read_frame(ff_ctx->ff->format_ctx, ff_ctx->packet) >= 0)
+    {
+        v = eina_array_data_get(ff_ctx->ff->videos, ff_ctx->ff->video_index);
+        printf(" stream index : %d %d %d\n",
+               ff_ctx->packet->stream_index,
+               ff_ctx->ff->video_index,
+               v->stream_index);
+        if (ff_ctx->packet->stream_index == v->stream_index)
+        {
+            int response;
+
+            printf("AVPacket->pts %lld\n",
+                   ff_ctx->packet->pts);
+
+            response = avcodec_send_packet(ff_ctx->ff->codec_ctx, ff_ctx->packet);
+            if (response < 0)
+                return ECORE_CALLBACK_RENEW;
+            while (response >= 0)
+            {
+                response = avcodec_receive_frame(ff_ctx->ff->codec_ctx, ff_ctx->frame);
+                if (response == AVERROR(EAGAIN) || response == AVERROR_EOF)
+                {
+                    break;
+                }
+                else if (response < 0) {
+                    return response;
+                }
+
+                if (response >= 0)
+                {
+                    printf("fame %d: size %d x %d\n",
+                        ff_ctx->ff->codec_ctx->frame_number,
+                           ff_ctx->frame->width,
+                           ff_ctx->frame->height);
+                }
+            }
+        }
+    }
+#endif
+
+    return ECORE_CALLBACK_RENEW;
+}
+
+void
+print_info(FFmpeg *ff, int w, int h)
+{
+    int num, den;
+    printf(" * video size: %d %d\n", w, h);
+    printf(" * duration  : %f s\n", ff_len_get(ff));
+    _ff_fps_get(ff, &num, &den);
+    printf(" * video fps : %d %d  %.2f %.2f\n", num, den, ff_fps_get(ff), 1.0 / ff_fps_get(ff));
+}
+
+int main(int argc, char *argv[])
+{
+    FFmpeg *ff;
+    int res;
+
+    Ecore_Animator *anim;
+    Ecore_Evas *ee;
+    Evas *evas;
+    Evas_Object *o;
+    int w;
+    int h;
+
+    if (argc < 2)
+    {
+        printf("Usage: %s file\n", argv[0]);
+        return 1;
+    }
+
+    ecore_evas_init();
+
+    ee = ecore_evas_new("software_gdi", 1, 1, 0, 0, NULL);
+    if (!ee)
+    {
+        ecore_evas_shutdown();
+        return 1;
+    }
+    ecore_evas_callback_delete_request_set(ee, _quit);
+    ecore_evas_callback_resize_set(ee, _resize);
+
+    evas = ecore_evas_get(ee);
+
+    o = evas_object_image_filled_add(evas);
+    evas_object_move(o, 0, 0);
+    evas_object_show(o);
+
+    ff = ff_new();
+    if (!ff)
+    {
+        printf("can not create ff\n");
+        return 1;
+    }
+
+    res= ff_file_open(ff, argv[1]);
+    if (!res)
+    {
+        printf("can not open file%s\n", argv[1]);
+        return 1;
+    }
+    ff_size_get(ff, &w, &h);
+    print_info(ff, w, h);
+
+    FF_Ctx ff_ctx;
+
+    ff_ctx.current_frame = 0;
+    ff_ctx.img = o;
+    ff_ctx.ff = ff;
+    ff_ctx.frame = av_frame_alloc();
+    if (!ff_ctx.frame)
+    {
+        printf("av_frame_alloc() failed\n");
+        return 0;
+    }
+
+    ff_ctx.packet = av_packet_alloc();
+    if (!ff_ctx.packet)
+    {
+        printf("av_packet_alloc() failed\n");
+        return 0;
+    }
+
+    ff_ctx.swscale_ctx = sws_getContext(w, h, AV_PIX_FMT_YUV420P,
+                                        w, h, AV_PIX_FMT_RGB32,
+                                        SWS_BILINEAR, NULL, NULL, NULL);
+    if (!ff_ctx.swscale_ctx)
+    {
+        printf("sws_alloc_context() failed\n");
+        return 0;
+    }
+
+    ecore_animator_frametime_set(1.0 / ff_fps_get(ff));
+    anim = ecore_animator_add(display_frame_cb, &ff_ctx);
+    if (!anim)
+    {
+        printf("no anim\n");
+        return 0;
+    }
+
+    ecore_evas_resize(ee, w, h);
+    ecore_evas_show(ee);
+
+    ecore_main_loop_begin();
+
+    ff_file_close(ff);
+    ff_free(ff);
+
+    ecore_evas_shutdown();
+
+    return 0;
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.

Reply via email to