286 lines
8.3 KiB
C
286 lines
8.3 KiB
C
/* 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++;
|
|
|
|
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)
|
|
{
|
|
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);
|
|
unsigned char *iter_src;
|
|
unsigned char **data;
|
|
unsigned char **iter_dst;
|
|
int i;
|
|
|
|
data = evas_object_image_data_get(ff_ctx->img, 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++)
|
|
{
|
|
*iter_dst = NULL;
|
|
*iter_dst = iter_src;
|
|
iter_dst++;
|
|
iter_src += ff_ctx->frame->linesize[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 = evas_object_image_data_set(ff_ctx->img, 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(NULL, 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);
|
|
|
|
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);
|
|
|
|
o = evas_object_image_filled_add(evas);
|
|
|
|
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;
|
|
}
|
|
|
|
evas_object_move(o, 0, 0);
|
|
evas_object_resize(o, w, h);
|
|
evas_object_show(o);
|
|
|
|
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;
|
|
}
|