/* gcc -g -Wall -Wextra -o ffmpeg main.c ffmpeg.c `pkg-config --cflags --libs ecore-evas libavcodec libavformat libavutil libswscale ecore-evas` */ #include #include #include #include #include #include #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; }