28 # undef AVIIF_KEYFRAME
34 fcc = mmioFOURCC('N', 'o', 'n', 'e'); \
36 if (fcc == BI_RLE8) { \
37 fcc = mmioFOURCC('R', 'l', 'e', '8'); \
49 #include <sys/types.h>
80 # include <libavcodec/avcodec.h>
81 # include <libavformat/avformat.h>
82 # include <libavutil/imgutils.h>
83 # include <libavutil/rational.h>
84 # include <libswscale/swscale.h>
109 # define PATHSEPARATOR '\\'
111 # define PATHSEPARATOR '/'
114 static int an_stringdec(
const char *
string,
char *head,
char *tail,
unsigned short *numlen)
116 unsigned short len, nume, nums = 0;
120 len = strlen(
string);
123 for (i =
len - 1; i >= 0; i--) {
127 if (isdigit(
string[i])) {
144 strcpy(tail, &
string[nume + 1]);
145 strcpy(head,
string);
147 *numlen = nume - nums + 1;
148 return ((
int)atoi(&(
string[nums])));
151 strcpy(head,
string);
157 char *
string,
const char *head,
const char *tail,
unsigned short numlen,
int pic)
163 static void free_anim_avi(
struct anim *
anim)
183 AVIStreamGetFrameClose(
anim->pgf);
187 for (i = 0; i <
anim->avistreams; i++) {
188 AVIStreamRelease(
anim->pavi[i]);
190 anim->avistreams = 0;
192 if (
anim->pfileopen) {
193 AVIFileRelease(
anim->pfile);
204 static void free_anim_ffmpeg(
struct anim *
anim);
210 printf(
"free anim, anim == NULL\n");
221 free_anim_ffmpeg(
anim);
252 AVDictionaryEntry *entry =
NULL;
255 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"METADATA FETCH\n");
258 entry = av_dict_get(
anim->pFormatCtx->
metadata,
"", entry, AV_DICT_IGNORE_SUFFIX);
311 #if !(defined(WITH_AVI) || defined(WITH_FFMPEG))
334 static int startavi(
struct anim *
anim)
340 int i, firstvideo = -1;
344 LPBITMAPINFOHEADER lpbi;
353 printf(
"Can't open avi: %s\n",
anim->
name);
366 if (AVIFileGetStream(
anim->pfile, &
anim->pavi[i], 0
L, i) != AVIERR_OK) {
370 AVIStreamInfo(
anim->pavi[i], &avis,
sizeof(avis));
371 if ((avis.fccType == streamtypeVIDEO) && (firstvideo == -1)) {
372 if (streamcount > 0) {
384 l =
sizeof(abFormat);
385 AVIStreamReadFormat(
anim->pavi[i], 0, &abFormat, &
l);
386 lpbi = (LPBITMAPINFOHEADER)abFormat;
391 FIXCC(avis.fccHandler);
393 printf(
"Can't find AVI decoder for type : %4.4hs/%4.4hs\n",
394 (LPSTR)&avis.fccType,
395 (LPSTR)&avis.fccHandler);
401 anim->avistreams = i;
406 if ((
anim->avistreams == 0) || (firstvideo == -1)) {
411 anim->firstvideo = firstvideo;
422 printf(
"Error loading avi: %s\n",
anim->
name);
440 printf(
"x:%d y:%d size:%d interl:%d dur:%d\n",
464 if (
anim->avistreams) {
465 LPBITMAPINFOHEADER lpbi;
468 lpbi = AVIStreamGetFrame(
anim->pgf, position + AVIStreamStart(
anim->pavi[
anim->firstvideo]));
485 printf(
"Error reading frame from AVI: '%s'\n",
anim->
name);
507 return (
anim->
x & 31) != 0;
510 static int startffmpeg(
struct anim *
anim)
512 int i, video_stream_index;
515 AVFormatContext *pFormatCtx =
NULL;
516 AVCodecContext *pCodecCtx;
517 AVRational frame_rate;
518 AVStream *video_stream;
524 int srcRange, dstRange, brightness, contrast, saturation;
526 const int *inv_table;
538 if (avformat_find_stream_info(pFormatCtx,
NULL) < 0) {
539 avformat_close_input(&pFormatCtx);
543 av_dump_format(pFormatCtx, 0,
anim->
name, 0);
546 video_stream_index = -1;
548 for (i = 0; i < pFormatCtx->nb_streams; i++) {
549 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
550 if (streamcount > 0) {
554 video_stream_index = i;
559 if (video_stream_index == -1) {
560 avformat_close_input(&pFormatCtx);
564 video_stream = pFormatCtx->streams[video_stream_index];
567 pCodec = avcodec_find_decoder(video_stream->codecpar->codec_id);
568 if (pCodec ==
NULL) {
569 avformat_close_input(&pFormatCtx);
573 pCodecCtx = avcodec_alloc_context3(
NULL);
574 avcodec_parameters_to_context(pCodecCtx, video_stream->codecpar);
575 pCodecCtx->workaround_bugs = FF_BUG_AUTODETECT;
577 if (pCodec->capabilities & AV_CODEC_CAP_AUTO_THREADS) {
578 pCodecCtx->thread_count = 0;
584 if (pCodec->capabilities & AV_CODEC_CAP_FRAME_THREADS) {
585 pCodecCtx->thread_type = FF_THREAD_FRAME;
587 else if (pCodec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {
588 pCodecCtx->thread_type = FF_THREAD_SLICE;
591 if (avcodec_open2(pCodecCtx, pCodec,
NULL) < 0) {
592 avformat_close_input(&pFormatCtx);
595 if (pCodecCtx->pix_fmt == AV_PIX_FMT_NONE) {
596 avcodec_free_context(&
anim->pCodecCtx);
597 avformat_close_input(&pFormatCtx);
601 double video_start = 0;
602 double pts_time_base = av_q2d(video_stream->time_base);
604 if (video_stream->start_time != AV_NOPTS_VALUE) {
605 video_start = video_stream->start_time * pts_time_base;
608 frame_rate = av_guess_frame_rate(pFormatCtx, video_stream,
NULL);
612 if (video_stream->nb_frames != 0) {
617 if (frame_rate.den != 0 && pFormatCtx->duration > 0) {
619 double container_sec = pFormatCtx->duration / (
double)AV_TIME_BASE;
620 if (stream_sec > 4.0 * container_sec) {
633 if (video_stream->duration != AV_NOPTS_VALUE) {
634 stream_dur = video_stream->duration * pts_time_base;
637 double audio_start = 0;
644 for (i = 0; i < pFormatCtx->nb_streams; i++) {
645 if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
646 AVStream *audio_stream = pFormatCtx->streams[i];
647 if (audio_stream->start_time != AV_NOPTS_VALUE) {
648 audio_start = audio_stream->start_time * av_q2d(audio_stream->time_base);
654 if (video_start > audio_start) {
655 stream_dur = (
double)pFormatCtx->duration / AV_TIME_BASE - (video_start - audio_start);
661 stream_dur = (
double)pFormatCtx->duration / AV_TIME_BASE;
667 double ctx_start = 0;
668 if (pFormatCtx->start_time != AV_NOPTS_VALUE) {
669 ctx_start = (
double)pFormatCtx->start_time / AV_TIME_BASE;
672 frs_num = frame_rate.num;
673 frs_den = frame_rate.den;
675 frs_den *= AV_TIME_BASE;
677 while (frs_num % 10 == 0 && frs_den >= 2.0 && frs_num > 10) {
690 anim->
x = pCodecCtx->width;
691 anim->
y = pCodecCtx->height;
693 anim->pFormatCtx = pFormatCtx;
694 anim->pCodecCtx = pCodecCtx;
695 anim->pCodec = pCodec;
696 anim->videoStream = video_stream_index;
703 anim->cur_frame_final = 0;
705 anim->cur_key_frame_pts = -1;
706 anim->cur_packet = av_packet_alloc();
707 anim->cur_packet->stream_index = -1;
709 anim->pFrame = av_frame_alloc();
710 anim->pFrameComplete =
false;
711 anim->pFrameDeinterlaced = av_frame_alloc();
712 anim->pFrameRGB = av_frame_alloc();
714 if (need_aligned_ffmpeg_buffer(
anim)) {
715 anim->pFrameRGB->format = AV_PIX_FMT_RGBA;
719 if (av_frame_get_buffer(
anim->pFrameRGB, 32) < 0) {
720 fprintf(stderr,
"Could not allocate frame data.\n");
721 avcodec_free_context(&
anim->pCodecCtx);
722 avformat_close_input(&
anim->pFormatCtx);
723 av_packet_free(&
anim->cur_packet);
724 av_frame_free(&
anim->pFrameRGB);
725 av_frame_free(&
anim->pFrameDeinterlaced);
726 av_frame_free(&
anim->pFrame);
733 fprintf(stderr,
"ffmpeg has changed alloc scheme ... ARGHHH!\n");
734 avcodec_free_context(&
anim->pCodecCtx);
735 avformat_close_input(&
anim->pFormatCtx);
736 av_packet_free(&
anim->cur_packet);
737 av_frame_free(&
anim->pFrameRGB);
738 av_frame_free(&
anim->pFrameDeinterlaced);
739 av_frame_free(&
anim->pFrame);
745 av_image_fill_arrays(
anim->pFrameDeinterlaced->data,
746 anim->pFrameDeinterlaced->linesize,
748 anim->pCodecCtx->width,
749 anim->pCodecCtx->height,
751 "ffmpeg deinterlace"),
752 anim->pCodecCtx->pix_fmt,
753 anim->pCodecCtx->width,
754 anim->pCodecCtx->height,
758 anim->img_convert_ctx = sws_getContext(
anim->
x,
760 anim->pCodecCtx->pix_fmt,
764 SWS_BILINEAR | SWS_PRINT_INFO | SWS_FULL_CHR_H_INT,
769 if (!
anim->img_convert_ctx) {
770 fprintf(stderr,
"Can't transform color space??? Bailing out...\n");
771 avcodec_free_context(&
anim->pCodecCtx);
772 avformat_close_input(&
anim->pFormatCtx);
773 av_packet_free(&
anim->cur_packet);
774 av_frame_free(&
anim->pFrameRGB);
775 av_frame_free(&
anim->pFrameDeinterlaced);
776 av_frame_free(&
anim->pFrame);
782 if (!sws_getColorspaceDetails(
anim->img_convert_ctx,
790 srcRange = srcRange ||
anim->pCodecCtx->color_range == AVCOL_RANGE_JPEG;
793 if (sws_setColorspaceDetails(
anim->img_convert_ctx,
801 fprintf(stderr,
"Warning: Could not set libswscale colorspace details.\n");
805 fprintf(stderr,
"Warning: Could not set libswscale colorspace details.\n");
817 static void ffmpeg_postprocess(
struct anim *
anim)
819 AVFrame *input =
anim->pFrame;
823 if (!
anim->pFrameComplete) {
829 if (input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) {
832 "data not read properly...\n");
836 av_log(
anim->pFormatCtx,
838 " POSTPROC: anim->pFrame planes: %p %p %p %p\n",
847 anim->pCodecCtx->pix_fmt,
848 anim->pCodecCtx->width,
849 anim->pCodecCtx->height) < 0) {
853 input =
anim->pFrameDeinterlaced;
857 if (!need_aligned_ffmpeg_buffer(
anim)) {
858 av_image_fill_arrays(
anim->pFrameRGB->data,
859 anim->pFrameRGB->linesize,
860 (
unsigned char *)ibuf->
rect,
867 # if defined(__x86_64__) || defined(_M_X64)
872 int *dstStride =
anim->pFrameRGB->linesize;
874 const int dstStride2[4] = {-dstStride[0], 0, 0, 0};
875 uint8_t *dst2[4] = {dst[0] + (
anim->
y - 1) * dstStride[0], 0, 0, 0};
877 sws_scale(
anim->img_convert_ctx,
878 (
const uint8_t *
const *)input->data,
886 int *dstStride =
anim->pFrameRGB->linesize;
888 const int dstStride2[4] = {dstStride[0], 0, 0, 0};
889 uint8_t *dst2[4] = {dst[0], 0, 0, 0};
894 sws_scale(
anim->img_convert_ctx,
895 (
const uint8_t *
const *)input->data,
905 h = (ibuf->
y + 1) / 2;
908 for (
y = 0;
y < h;
y++) {
909 unsigned char tmp[4];
910 unsigned int *tmp_l = (
unsigned int *)tmp;
912 for (
x = 0;
x <
w;
x++) {
923 *(
unsigned int *)
top = *tmp_l;
932 if (need_aligned_ffmpeg_buffer(
anim)) {
936 memcpy(buf_dst, buf_src,
anim->
x * 4);
937 buf_dst +=
anim->
x * 4;
938 buf_src +=
anim->pFrameRGB->linesize[0];
949 static int ffmpeg_decode_video_frame(
struct anim *
anim)
953 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
" DECODE VIDEO FRAME\n");
955 if (
anim->cur_packet->stream_index ==
anim->videoStream) {
956 av_packet_unref(
anim->cur_packet);
957 anim->cur_packet->stream_index = -1;
960 while ((rval = av_read_frame(
anim->pFormatCtx,
anim->cur_packet)) >= 0) {
961 av_log(
anim->pFormatCtx,
963 "%sREAD: strID=%d (VID: %d) dts=%" PRId64 " pts=%" PRId64 " %s\n",
964 (
anim->cur_packet->stream_index ==
anim->videoStream) ?
"->" :
" ",
965 anim->cur_packet->stream_index,
967 (
anim->cur_packet->dts == AV_NOPTS_VALUE) ? -1 : (
int64_t)
anim->cur_packet->dts,
968 (
anim->cur_packet->pts == AV_NOPTS_VALUE) ? -1 : (
int64_t)
anim->cur_packet->pts,
969 (
anim->cur_packet->flags & AV_PKT_FLAG_KEY) ?
" KEY" :
"");
970 if (
anim->cur_packet->stream_index ==
anim->videoStream) {
971 anim->pFrameComplete = 0;
973 avcodec_send_packet(
anim->pCodecCtx,
anim->cur_packet);
974 anim->pFrameComplete = avcodec_receive_frame(
anim->pCodecCtx,
anim->pFrame) == 0;
976 if (
anim->pFrameComplete) {
979 if (
anim->pFrame->key_frame) {
980 anim->cur_key_frame_pts =
anim->cur_pts;
982 av_log(
anim->pFormatCtx,
984 " FRAME DONE: cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
985 (
anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (
int64_t)
anim->pFrame->pts,
990 av_packet_unref(
anim->cur_packet);
991 anim->cur_packet->stream_index = -1;
994 if (rval == AVERROR_EOF) {
996 anim->pFrameComplete = 0;
998 avcodec_send_packet(
anim->pCodecCtx,
NULL);
999 anim->pFrameComplete = avcodec_receive_frame(
anim->pCodecCtx,
anim->pFrame) == 0;
1001 if (
anim->pFrameComplete) {
1004 if (
anim->pFrame->key_frame) {
1005 anim->cur_key_frame_pts =
anim->cur_pts;
1007 av_log(
anim->pFormatCtx,
1009 " FRAME DONE (after EOF): cur_pts=%" PRId64 ", guessed_pts=%" PRId64 "\n",
1010 (
anim->pFrame->pts == AV_NOPTS_VALUE) ? -1 : (
int64_t)
anim->pFrame->pts,
1017 av_packet_unref(
anim->cur_packet);
1018 anim->cur_packet->stream_index = -1;
1020 av_log(
anim->pFormatCtx,
1022 " DECODE READ FAILED: av_read_frame() "
1023 "returned error: %s\n",
1030 static int match_format(
const char *
name, AVFormatContext *pFormatCtx)
1035 const char *
names = pFormatCtx->iformat->name;
1041 namelen = strlen(
name);
1042 while ((p = strchr(
names,
','))) {
1052 static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
1054 static const char *byte_seek_list[] = {
"mpegts", 0};
1057 if (pFormatCtx->iformat->flags & AVFMT_TS_DISCONT) {
1064 if (match_format(*p++, pFormatCtx)) {
1074 AVStream *v_st =
anim->pFormatCtx->streams[
anim->videoStream];
1075 AVRational frame_rate = v_st->r_frame_rate;
1076 AVRational time_base = v_st->time_base;
1077 double steps_per_frame = (
double)(frame_rate.den * time_base.den) /
1078 (
double)(frame_rate.num * time_base.num);
1084 int64_t pts = pts_to_search - (steps_per_frame / 2);
1103 AVStream *v_st =
anim->pFormatCtx->streams[
anim->videoStream];
1104 int64_t start_pts = v_st->start_time;
1105 AVRational frame_rate = v_st->r_frame_rate;
1106 AVRational time_base = v_st->time_base;
1108 double steps_per_frame = (
double)(frame_rate.den * time_base.den) /
1109 (
double)(frame_rate.num * time_base.num);
1111 pts_to_search = round(position * steps_per_frame);
1113 if (start_pts != AV_NOPTS_VALUE) {
1114 pts_to_search += start_pts;
1117 return pts_to_search;
1121 static bool ffmpeg_pts_matches_last_frame(
struct anim *
anim,
int64_t pts_to_search)
1123 if (
anim->pFrame &&
anim->cur_frame_final) {
1131 static bool ffmpeg_is_first_frame_decode(
struct anim *
anim,
int position)
1137 static void ffmpeg_decode_video_frame_scan(
struct anim *
anim,
int64_t pts_to_search)
1139 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"FETCH: within current GOP\n");
1141 av_log(
anim->pFormatCtx,
1143 "SCAN start: considering pts=%" PRId64 " in search of %" PRId64 "\n",
1147 int64_t start_gop_frame =
anim->cur_key_frame_pts;
1148 bool scan_fuzzy =
false;
1150 while (
anim->cur_pts < pts_to_search) {
1151 av_log(
anim->pFormatCtx,
1156 if (!ffmpeg_decode_video_frame(
anim)) {
1160 if (start_gop_frame !=
anim->cur_key_frame_pts) {
1164 if (
anim->cur_pts < pts_to_search &&
1165 anim->cur_pts +
anim->pFrame->pkt_duration > pts_to_search) {
1167 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"SCAN fuzzy frame match\n");
1173 if (start_gop_frame !=
anim->cur_key_frame_pts) {
1176 av_log(
anim->pFormatCtx,
1178 "SCAN failed: completely lost in stream, "
1179 "bailing out at PTS=%" PRId64 ", searching for PTS=%" PRId64 "\n",
1184 if (scan_fuzzy ||
anim->cur_pts == pts_to_search) {
1185 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"SCAN HAPPY: we found our PTS!\n");
1188 av_log(
anim->pFormatCtx, AV_LOG_ERROR,
"SCAN UNHAPPY: PTS not matched!\n");
1197 static int ffmpeg_generic_seek_workaround(
struct anim *
anim,
1201 AVStream *v_st =
anim->pFormatCtx->streams[
anim->videoStream];
1202 AVRational frame_rate = v_st->r_frame_rate;
1203 AVRational time_base = v_st->time_base;
1205 double steps_per_frame = (
double)(frame_rate.den * time_base.den) /
1206 (
double)(frame_rate.num * time_base.num);
1208 int64_t current_pts = *requested_pts;
1211 int64_t cur_pts, prev_pts = -1;
1214 while (current_pts != 0) {
1215 current_pts = *requested_pts - (
int64_t)round(offset * steps_per_frame);
1216 current_pts =
MAX2(current_pts, 0);
1219 if (av_seek_frame(
anim->pFormatCtx,
anim->videoStream, current_pts, AVSEEK_FLAG_BACKWARD) <
1225 AVPacket *read_packet = av_packet_alloc();
1226 while (av_read_frame(
anim->pFormatCtx, read_packet) >= 0) {
1227 if (read_packet->stream_index ==
anim->videoStream) {
1230 av_packet_unref(read_packet);
1234 bool is_key_frame = read_packet->flags & AV_PKT_FLAG_KEY;
1239 av_packet_free(&read_packet);
1242 if (cur_pts <= pts_to_search) {
1248 if (cur_pts == prev_pts) {
1258 *requested_pts = current_pts;
1261 return av_seek_frame(
anim->pFormatCtx,
anim->videoStream, current_pts, AVSEEK_FLAG_BACKWARD);
1265 static int ffmpeg_seek_to_key_frame(
struct anim *
anim,
1291 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"TC INDEX seek pos = %" PRId64 "\n",
pos);
1292 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"TC INDEX seek pts = %" PRIu64 "\n", pts);
1293 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"TC INDEX seek dts = %" PRIu64 "\n", dts);
1295 if (ffmpeg_seek_by_byte(
anim->pFormatCtx)) {
1296 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"... using BYTE pos\n");
1298 ret = av_seek_frame(
anim->pFormatCtx, -1,
pos, AVSEEK_FLAG_BYTE);
1301 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"... using PTS pos\n");
1302 ret = av_seek_frame(
1303 anim->pFormatCtx,
anim->videoStream,
anim->cur_key_frame_pts, AVSEEK_FLAG_BACKWARD);
1309 pos = ffmpeg_get_seek_pts(
anim, pts_to_search);
1310 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"NO INDEX final seek pos = %" PRId64 "\n",
pos);
1312 AVFormatContext *format_ctx =
anim->pFormatCtx;
1314 if (format_ctx->iformat->read_seek2 || format_ctx->iformat->read_seek) {
1315 ret = av_seek_frame(
anim->pFormatCtx,
anim->videoStream,
pos, AVSEEK_FLAG_BACKWARD);
1318 ret = ffmpeg_generic_seek_workaround(
anim, &
pos, pts_to_search);
1319 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"Adjusted final seek pos = %" PRId64 "\n",
pos);
1324 AVPacket *current_gop_start_packet = av_packet_alloc();
1325 while (av_read_frame(
anim->pFormatCtx, current_gop_start_packet) >= 0) {
1326 if (current_gop_start_packet->stream_index ==
anim->videoStream) {
1329 av_packet_unref(current_gop_start_packet);
1332 current_gop_start_packet->dts);
1334 av_packet_free(¤t_gop_start_packet);
1335 bool same_gop = gop_pts ==
anim->cur_key_frame_pts;
1341 if (cur_pts == gop_pts) {
1345 AVPacket *temp = av_packet_alloc();
1347 while (av_read_frame(
anim->pFormatCtx, temp) >= 0) {
1349 if (temp->stream_index ==
anim->videoStream && temp_pts == cur_pts) {
1352 av_packet_unref(temp);
1354 av_packet_free(&temp);
1358 anim->cur_key_frame_pts = gop_pts;
1360 av_seek_frame(
anim->pFormatCtx,
anim->videoStream,
pos, AVSEEK_FLAG_BACKWARD);
1365 av_log(
anim->pFormatCtx,
1368 "error while seeking to DTS = %" PRId64 " (frameno = %d, PTS = %" PRId64
1369 "): errcode = %d\n",
1377 avcodec_flush_buffers(
anim->pCodecCtx);
1381 if (
anim->cur_packet->stream_index ==
anim->videoStream) {
1382 av_packet_unref(
anim->cur_packet);
1383 anim->cur_packet->stream_index = -1;
1395 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"FETCH: pos=%d\n", position);
1398 int64_t pts_to_search = ffmpeg_get_pts_to_search(
anim, tc_index, position);
1399 AVStream *v_st =
anim->pFormatCtx->streams[
anim->videoStream];
1400 double frame_rate = av_q2d(v_st->r_frame_rate);
1401 double pts_time_base = av_q2d(v_st->time_base);
1402 int64_t start_pts = v_st->start_time;
1404 av_log(
anim->pFormatCtx,
1406 "FETCH: looking for PTS=%" PRId64 " (pts_timebase=%g, frame_rate=%g, start_pts=%" PRId64
1413 if (ffmpeg_pts_matches_last_frame(
anim, pts_to_search)) {
1414 av_log(
anim->pFormatCtx,
1416 "FETCH: frame repeat: pts: %" PRId64 "\n",
1420 return anim->cur_frame_final;
1424 av_log(
anim->pFormatCtx, AV_LOG_DEBUG,
"FETCH: no seek necessary, just continue...\n");
1425 ffmpeg_decode_video_frame(
anim);
1427 else if (ffmpeg_seek_to_key_frame(
anim, position, tc_index, pts_to_search) >= 0) {
1428 ffmpeg_decode_video_frame_scan(
anim, pts_to_search);
1453 (
size_t)4 *
anim->
x *
anim->
y, 32,
"ffmpeg ibuf");
1458 ffmpeg_postprocess(
anim);
1464 return anim->cur_frame_final;
1467 static void free_anim_ffmpeg(
struct anim *
anim)
1473 if (
anim->pCodecCtx) {
1474 avcodec_free_context(&
anim->pCodecCtx);
1475 avformat_close_input(&
anim->pFormatCtx);
1476 av_packet_free(&
anim->cur_packet);
1478 av_frame_free(&
anim->pFrame);
1480 if (!need_aligned_ffmpeg_buffer(
anim)) {
1485 av_image_fill_arrays(
anim->pFrameRGB->data,
1486 anim->pFrameRGB->linesize,
1493 av_frame_free(&
anim->pFrameRGB);
1494 av_frame_free(&
anim->pFrameDeinterlaced);
1496 sws_freeContext(
anim->img_convert_ctx);
1519 free_anim_avi(
anim);
1523 free_anim_ffmpeg(
anim);
1547 if (startavi(
anim)) {
1548 printf(
"couldn't start avi\n");
1556 if (startffmpeg(
anim)) {
1586 char head[256], tail[256];
1587 unsigned short digits;
1643 ibuf = avi_fetchibuf(
anim, position);
1651 ibuf = ffmpeg_fetchibuf(
anim, position, tc);
1693 double frs_sec_base_double;
1698 *frs_sec = SHRT_MAX;
1707 *frs_sec_base = (
float)(frs_sec_base_double / AV_TIME_BASE);
1710 *frs_sec_base = (
float)frs_sec_base_double;
1714 *frs_sec_base = (
float)frs_sec_base_double;
AviError AVI_close(AviMovie *movie)
void * AVI_read_frame(AviMovie *movie, AviFormat format, int frame, int stream)
AviError AVI_print_error(AviError error)
int AVI_get_stream(AviMovie *movie, int avist_type, int stream_num)
AviError AVI_open_movie(const char *name, AviMovie *movie)
typedef float(TangentPoint)[2]
bool BLI_path_is_rel(const char *path) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
void BLI_path_sequence_encode(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
int BLI_strncasecmp(const char *s1, const char *s2, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
int BLI_strcasecmp(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
size_t BLI_snprintf(char *__restrict dst, size_t maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
int BLI_system_thread_count(void)
Compatibility-like things for windows.
typedef double(DMatrix)[4][4]
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble top
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble bottom
@ COLOR_ROLE_DEFAULT_BYTE
struct ImBuf * IMB_allocImBuf(unsigned int x, unsigned int y, unsigned char planes, unsigned int flags)
void IMB_freeImBuf(struct ImBuf *ibuf)
void IMB_filtery(struct ImBuf *ibuf)
int IMB_anim_index_get_frame_index(struct anim *anim, IMB_Timecode_Type tc, int position)
void IMB_refImBuf(struct ImBuf *ibuf)
struct ImBuf * IMB_loadiffname(const char *filepath, int flags, char colorspace[IM_MAX_SPACE])
void IMB_convert_rgba_to_abgr(struct ImBuf *ibuf)
struct ImBuf * IMB_ibImageFromMemory(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE], const char *descr)
int imb_get_anim_type(const char *filepath)
Contains defines and structs used throughout the imbuf module.
uint64_t IMB_indexer_get_seek_pos(struct anim_index *idx, int frame_index)
uint64_t IMB_indexer_get_seek_pos_pts(struct anim_index *idx, int frame_index)
struct anim_index * IMB_anim_open_index(struct anim *anim, IMB_Timecode_Type tc)
uint64_t IMB_indexer_get_seek_pos_dts(struct anim_index *idx, int frame_index)
void IMB_free_indices(struct anim *anim)
int IMB_indexer_get_duration(struct anim_index *idx)
struct anim * IMB_anim_open_proxy(struct anim *anim, IMB_Proxy_Size preview_size)
int IMB_indexer_can_scan(struct anim_index *idx, int old_frame_index, int new_frame_index)
uint64_t IMB_indexer_get_pts(struct anim_index *idx, int frame_index)
int IMB_indexer_get_frame_index(struct anim_index *idx, int frameno)
Read Guarded memory(de)allocation.
static int an_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
void IMB_close_anim_proxies(struct anim *anim)
bool IMB_anim_get_fps(struct anim *anim, short *frs_sec, float *frs_sec_base, bool no_av_base)
void IMB_free_anim(struct anim *anim)
int ismovie(const char *UNUSED(filepath))
void IMB_close_anim(struct anim *anim)
static ImBuf * movie_fetchibuf(struct anim *UNUSED(anim), int UNUSED(position))
static void free_anim_movie(struct anim *UNUSED(anim))
int IMB_anim_get_image_height(struct anim *anim)
static int startmovie(struct anim *UNUSED(anim))
struct anim * IMB_open_anim(const char *name, int ib_flags, int streamindex, char colorspace[IM_MAX_SPACE])
static void an_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
struct IDProperty * IMB_anim_load_metadata(struct anim *anim)
struct ImBuf * IMB_anim_previewframe(struct anim *anim)
void IMB_suffix_anim(struct anim *anim, const char *suffix)
double IMD_anim_get_offset(struct anim *anim)
int IMB_anim_get_image_width(struct anim *anim)
struct ImBuf * IMB_anim_absolute(struct anim *anim, int position, IMB_Timecode_Type tc, IMB_Proxy_Size preview_size)
static ImBuf * anim_getnew(struct anim *anim)
bool IMB_anim_can_produce_frames(const struct anim *anim)
int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
void colorspace_set_default_role(char *colorspace, int size, int role)
ColorSpace * colormanage_colorspace_get_named(const char *name)
FFMPEG_INLINE int64_t timestamp_from_pts_or_dts(int64_t pts, int64_t dts)
FFMPEG_INLINE int64_t av_get_pts_from_frame(AVFrame *picture)
FFMPEG_INLINE int av_image_deinterlace(AVFrame *dst, const AVFrame *src, enum AVPixelFormat pix_fmt, int width, int height)
void(* MEM_freeN)(void *vmemh)
void *(* MEM_mallocN_aligned)(size_t len, size_t alignment, const char *str)
void *(* MEM_callocN)(size_t len, const char *str)
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt=1)
unsigned __int64 uint64_t
struct ColorSpace * rect_colorspace
char name[IMB_FILENAME_SIZE]
struct IDProperty * metadata