Example #1
0
static void index_rebuild_fallback_finish(FallbackIndexBuilderContext *context, int stop)
{
	struct anim *anim = context->anim;
	char fname[FILE_MAX];
	char fname_tmp[FILE_MAX];
	int i;

	for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
		if (context->proxy_sizes_in_use & proxy_sizes[i]) {
			AVI_close_compress(context->proxy_ctx[i]);
			MEM_freeN(context->proxy_ctx[i]);

			get_proxy_filename(anim, proxy_sizes[i], fname_tmp, TRUE);
			get_proxy_filename(anim, proxy_sizes[i], fname, FALSE);

			if (stop) {
				unlink(fname_tmp);
			}
			else {
				unlink(fname);
				rename(fname_tmp, fname);
			}
		}
	}
}
Example #2
0
static void free_proxy_output_ffmpeg(struct proxy_output_ctx *ctx,
                                     int rollback)
{
	int i;
	char fname[FILE_MAX];
	char fname_tmp[FILE_MAX];

	if (!ctx) {
		return;
	}

	if (!rollback) {
		while (add_to_proxy_output_ffmpeg(ctx, NULL)) {}
	}

	avcodec_flush_buffers(ctx->c);

	av_write_trailer(ctx->of);
	
	avcodec_close(ctx->c);
	
	for (i = 0; i < ctx->of->nb_streams; i++) {
		if (&ctx->of->streams[i]) {
			av_freep(&ctx->of->streams[i]);
		}
	}

	if (ctx->of->oformat) {
		if (!(ctx->of->oformat->flags & AVFMT_NOFILE)) {
			avio_close(ctx->of->pb);
		}
	}
	av_free(ctx->of);

	MEM_freeN(ctx->video_buffer);

	if (ctx->sws_ctx) {
		sws_freeContext(ctx->sws_ctx);

		MEM_freeN(ctx->frame->data[0]);
		av_free(ctx->frame);
	}

	get_proxy_filename(ctx->anim, ctx->proxy_size, 
	                   fname_tmp, TRUE);

	if (rollback) {
		unlink(fname_tmp);
	}
	else {
		get_proxy_filename(ctx->anim, ctx->proxy_size, 
		                   fname, FALSE);
		unlink(fname);
		BLI_rename(fname_tmp, fname);
	}
	
	MEM_freeN(ctx);
}
Example #3
0
IMB_Proxy_Size IMB_anim_proxy_get_existing(struct anim *anim)
{
	const int num_proxy_sizes = IMB_PROXY_MAX_SLOT;
	IMB_Proxy_Size existing = 0;
	int i;
	for (i = 0; i < num_proxy_sizes; ++i) {
		IMB_Proxy_Size proxy_size = proxy_sizes[i];
		char filename[FILE_MAX];
		get_proxy_filename(anim, proxy_size, filename, false);
		if (BLI_exists(filename)) {
			existing |= proxy_size;
		}
	}
	return existing;
}
Example #4
0
struct anim *IMB_anim_open_proxy(
        struct anim *anim, IMB_Proxy_Size preview_size)
{
	char fname[FILE_MAX];
	int i = IMB_proxy_size_to_array_index(preview_size);

	if (anim->proxy_anim[i]) {
		return anim->proxy_anim[i];
	}

	if (anim->proxies_tried & preview_size) {
		return NULL;
	}

	get_proxy_filename(anim, preview_size, fname, FALSE);

	anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0);
	
	anim->proxies_tried |= preview_size;

	return anim->proxy_anim[i];
}
Example #5
0
struct anim *IMB_anim_open_proxy(
        struct anim *anim, IMB_Proxy_Size preview_size)
{
	char fname[FILE_MAX];
	int i = IMB_proxy_size_to_array_index(preview_size);

	if (anim->proxy_anim[i]) {
		return anim->proxy_anim[i];
	}

	if (anim->proxies_tried & preview_size) {
		return NULL;
	}

	get_proxy_filename(anim, preview_size, fname, false);

	/* proxies are generated in the same color space as animation itself */
	anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0, anim->colorspace);
	
	anim->proxies_tried |= preview_size;

	return anim->proxy_anim[i];
}
Example #6
0
static IndexBuildContext *index_fallback_create_context(struct anim *anim, IMB_Timecode_Type UNUSED(tcs_in_use),
                                                        IMB_Proxy_Size proxy_sizes_in_use, int quality)
{
	FallbackIndexBuilderContext *context;
	int i;

	/* since timecode indices only work with ffmpeg right now,
	 * don't know a sensible fallback here...
	 *
	 * so no proxies, no game to play...
	 */
	if (proxy_sizes_in_use == IMB_PROXY_NONE) {
		return NULL;
	}

	context = MEM_callocN(sizeof(FallbackIndexBuilderContext), "fallback index builder context");

	context->anim = anim;
	context->proxy_sizes_in_use = proxy_sizes_in_use;

	memset(context->proxy_ctx, 0, sizeof(context->proxy_ctx));

	for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
		if (context->proxy_sizes_in_use & proxy_sizes[i]) {
			char fname[FILE_MAX];

			get_proxy_filename(anim, proxy_sizes[i], fname, TRUE);
			BLI_make_existing_file(fname);

			context->proxy_ctx[i] = alloc_proxy_output_avi(anim, fname,
			                                               anim->x * proxy_fac[i], anim->y * proxy_fac[i], quality);
		}
	}

	return (IndexBuildContext *)context;
}
Example #7
0
static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
        struct anim *anim,
        AVStream *st, int proxy_size, int width, int height,
        int quality)
{
	struct proxy_output_ctx *rv = MEM_callocN(
	        sizeof(struct proxy_output_ctx), "alloc_proxy_output");
	
	char fname[FILE_MAX];
	int ffmpeg_quality;

	/* JPEG requires this */
	width = round_up(width, 8);
	height = round_up(height, 8);

	rv->proxy_size = proxy_size;
	rv->anim = anim;

	get_proxy_filename(rv->anim, rv->proxy_size, fname, TRUE);
	BLI_make_existing_file(fname);

	rv->of = avformat_alloc_context();
	rv->of->oformat = av_guess_format("avi", NULL, NULL);
	
	BLI_strncpy(rv->of->filename, fname, sizeof(rv->of->filename));

	fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename);

	rv->st = avformat_new_stream(rv->of, NULL);
	rv->st->id = 0;

	rv->c = rv->st->codec;
	rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
	rv->c->codec_id = AV_CODEC_ID_MJPEG;
	rv->c->width = width;
	rv->c->height = height;

	rv->of->oformat->video_codec = rv->c->codec_id;
	rv->codec = avcodec_find_encoder(rv->c->codec_id);

	if (!rv->codec) {
		fprintf(stderr, "No ffmpeg MJPEG encoder available? "
		        "Proxy not built!\n");
		av_free(rv->of);
		return NULL;
	}

	if (rv->codec->pix_fmts) {
		rv->c->pix_fmt = rv->codec->pix_fmts[0];
	}
	else {
		rv->c->pix_fmt = PIX_FMT_YUVJ420P;
	}

	rv->c->sample_aspect_ratio =
	    rv->st->sample_aspect_ratio =
	        st->codec->sample_aspect_ratio;

	rv->c->time_base.den = 25;
	rv->c->time_base.num = 1;
	rv->st->time_base = rv->c->time_base;

	/* there's no  way to set JPEG quality in the same way as in AVI JPEG and image sequence,
	 * but this seems to be giving expected quality result */
	ffmpeg_quality = (int)(1.0f + 30.0f * (1.0f - (float)quality / 100.0f) + 0.5f);
	av_opt_set_int(rv->c, "qmin", ffmpeg_quality, 0);
	av_opt_set_int(rv->c, "qmax", ffmpeg_quality, 0);

	if (rv->of->flags & AVFMT_GLOBALHEADER) {
		rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
	}

	if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) {
		fprintf(stderr, "Couldn't open outputfile! "
		        "Proxy not built!\n");
		av_free(rv->of);
		return 0;
	}

	avcodec_open2(rv->c, rv->codec, NULL);

	rv->orig_height = av_get_cropped_height_from_codec(st->codec);

	if (st->codec->width != width || st->codec->height != height ||
	    st->codec->pix_fmt != rv->c->pix_fmt)
	{
		rv->frame = avcodec_alloc_frame();
		avpicture_fill((AVPicture *) rv->frame,
		               MEM_mallocN(avpicture_get_size(
		                               rv->c->pix_fmt,
		                               round_up(width, 16), height),
		                           "alloc proxy output frame"),
		               rv->c->pix_fmt, round_up(width, 16), height);

		rv->sws_ctx = sws_getContext(
		        st->codec->width,
		        rv->orig_height,
		        st->codec->pix_fmt,
		        width, height,
		        rv->c->pix_fmt,
		        SWS_FAST_BILINEAR | SWS_PRINT_INFO,
		        NULL, NULL, NULL);
	}

	if (avformat_write_header(rv->of, NULL) < 0) {
		fprintf(stderr, "Couldn't set output parameters? "
		        "Proxy not built!\n");
		av_free(rv->of);
		return 0;
	}

	return rv;
}
Example #8
0
static void index_rebuild_fallback(struct anim * anim,
                                   IMB_Timecode_Type UNUSED(tcs_in_use),
                                   IMB_Proxy_Size proxy_sizes_in_use,
                                   int quality,
                                   short *stop, short *do_update,
                                   float *progress)
{
    int cnt = IMB_anim_get_duration(anim, IMB_TC_NONE);
    int i, pos;
    AviMovie * proxy_ctx[IMB_PROXY_MAX_SLOT];
    char fname[FILE_MAXDIR+FILE_MAXFILE];
    char fname_tmp[FILE_MAXDIR+FILE_MAXFILE];

    memset(proxy_ctx, 0, sizeof(proxy_ctx));

    /* since timecode indices only work with ffmpeg right now,
       don't know a sensible fallback here...

       so no proxies, no game to play...
    */
    if (proxy_sizes_in_use == IMB_PROXY_NONE) {
        return;
    }

    for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
        if (proxy_sizes_in_use & proxy_sizes[i]) {
            char fname[FILE_MAXDIR+FILE_MAXFILE];

            get_proxy_filename(anim, proxy_sizes[i], fname, TRUE);
            BLI_make_existing_file(fname);

            proxy_ctx[i] = alloc_proxy_output_avi(
                               anim, fname,
                               anim->x * proxy_fac[i],
                               anim->y * proxy_fac[i],
                               quality);
        }
    }

    for (pos = 0; pos < cnt; pos++) {
        struct ImBuf * ibuf = IMB_anim_absolute(
                                  anim, pos, IMB_TC_NONE, IMB_PROXY_NONE);
        int next_progress = (int) ((double) pos / (double) cnt);

        if (*progress != next_progress) {
            *progress = next_progress;
            *do_update = 1;
        }

        if (*stop) {
            break;
        }

        IMB_flipy(ibuf);

        for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
            if (proxy_sizes_in_use & proxy_sizes[i]) {
                int x = anim->x * proxy_fac[i];
                int y = anim->y * proxy_fac[i];

                struct ImBuf * s_ibuf = IMB_scalefastImBuf(
                                            ibuf, x, y);

                IMB_convert_rgba_to_abgr(s_ibuf);

                AVI_write_frame (proxy_ctx[i], pos,
                                 AVI_FORMAT_RGB32,
                                 s_ibuf->rect, x * y * 4);

                /* note that libavi free's the buffer... */
                s_ibuf->rect = 0;

                IMB_freeImBuf(s_ibuf);
            }
        }
    }

    for (i = 0; i < IMB_PROXY_MAX_SLOT; i++) {
        if (proxy_sizes_in_use & proxy_sizes[i]) {
            AVI_close_compress (proxy_ctx[i]);
            MEM_freeN (proxy_ctx[i]);

            get_proxy_filename(anim, proxy_sizes[i],
                               fname_tmp, TRUE);
            get_proxy_filename(anim, proxy_sizes[i],
                               fname, FALSE);

            if (*stop) {
                unlink(fname_tmp);
            } else {
                rename(fname_tmp, fname);
            }
        }
    }
}
Example #9
0
static struct proxy_output_ctx * alloc_proxy_output_ffmpeg(
    struct anim * anim,
    AVStream * st, int proxy_size, int width, int height,
    int quality)
{
    struct proxy_output_ctx * rv = MEM_callocN(
                                       sizeof(struct proxy_output_ctx), "alloc_proxy_output");

    char fname[FILE_MAXDIR+FILE_MAXFILE];

    // JPEG requires this
    width = round_up(width, 8);
    height = round_up(height, 8);

    rv->proxy_size = proxy_size;
    rv->anim = anim;

    get_proxy_filename(rv->anim, rv->proxy_size, fname, TRUE);
    BLI_make_existing_file(fname);

    rv->of = avformat_alloc_context();
    rv->of->oformat = av_guess_format("avi", NULL, NULL);

    BLI_snprintf(rv->of->filename, sizeof(rv->of->filename), "%s", fname);

    fprintf(stderr, "Starting work on proxy: %s\n", rv->of->filename);

    rv->st = av_new_stream(rv->of, 0);
    rv->c = rv->st->codec;
    rv->c->codec_type = AVMEDIA_TYPE_VIDEO;
    rv->c->codec_id = CODEC_ID_MJPEG;
    rv->c->width = width;
    rv->c->height = height;

    rv->of->oformat->video_codec = rv->c->codec_id;
    rv->codec = avcodec_find_encoder(rv->c->codec_id);

    if (!rv->codec) {
        fprintf(stderr, "No ffmpeg MJPEG encoder available? "
                "Proxy not built!\n");
        av_free(rv->of);
        return NULL;
    }

    if (rv->codec->pix_fmts) {
        rv->c->pix_fmt = rv->codec->pix_fmts[0];
    } else {
        rv->c->pix_fmt = PIX_FMT_YUVJ420P;
    }

    rv->c->sample_aspect_ratio
        = rv->st->sample_aspect_ratio
          = st->codec->sample_aspect_ratio;

    rv->c->time_base.den = 25;
    rv->c->time_base.num = 1;
    rv->st->time_base = rv->c->time_base;

    if (rv->of->flags & AVFMT_GLOBALHEADER) {
        rv->c->flags |= CODEC_FLAG_GLOBAL_HEADER;
    }

    if (av_set_parameters(rv->of, NULL) < 0) {
        fprintf(stderr, "Couldn't set output parameters? "
                "Proxy not built!\n");
        av_free(rv->of);
        return 0;
    }

    if (avio_open(&rv->of->pb, fname, AVIO_FLAG_WRITE) < 0) {
        fprintf(stderr, "Couldn't open outputfile! "
                "Proxy not built!\n");
        av_free(rv->of);
        return 0;
    }

    avcodec_open(rv->c, rv->codec);

    rv->video_buffersize = 2000000;
    rv->video_buffer = (uint8_t*)MEM_mallocN(
                           rv->video_buffersize, "FFMPEG video buffer");

    rv->orig_height = st->codec->height;

    if (st->codec->width != width || st->codec->height != height
            || st->codec->pix_fmt != rv->c->pix_fmt) {
        rv->frame = avcodec_alloc_frame();
        avpicture_fill((AVPicture*) rv->frame,
                       MEM_mallocN(avpicture_get_size(
                                       rv->c->pix_fmt,
                                       round_up(width, 16), height),
                                   "alloc proxy output frame"),
                       rv->c->pix_fmt, round_up(width, 16), height);

        rv->sws_ctx = sws_getContext(
                          st->codec->width,
                          st->codec->height,
                          st->codec->pix_fmt,
                          width, height,
                          rv->c->pix_fmt,
                          SWS_FAST_BILINEAR | SWS_PRINT_INFO,
                          NULL, NULL, NULL);
    }

    av_write_header(rv->of);

    return rv;
}
Example #10
0
IndexBuildContext *IMB_anim_index_rebuild_context(struct anim *anim, IMB_Timecode_Type tcs_in_use,
                                                  IMB_Proxy_Size proxy_sizes_in_use, int quality,
                                                  const bool overwrite, GSet *file_list)
{
	IndexBuildContext *context = NULL;
	IMB_Proxy_Size proxy_sizes_to_build = proxy_sizes_in_use;
	int i;

	/* Don't generate the same file twice! */
	if (file_list) {
		for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) {
			IMB_Proxy_Size proxy_size = proxy_sizes[i];
			if (proxy_size & proxy_sizes_to_build) {
				char filename[FILE_MAX];
				get_proxy_filename(anim, proxy_size, filename, false);

				void **filename_key_p;
				if (!BLI_gset_ensure_p_ex(file_list, filename, &filename_key_p)) {
					*filename_key_p = BLI_strdup(filename);
				}
				else {
					proxy_sizes_to_build &= ~proxy_size;
					printf("Proxy: %s already registered for generation, skipping\n", filename);
				}
			}
		}
	}
	
	if (!overwrite) {
		IMB_Proxy_Size built_proxies = IMB_anim_proxy_get_existing(anim);
		if (built_proxies != 0) {

			for (i = 0; i < IMB_PROXY_MAX_SLOT; ++i) {
				IMB_Proxy_Size proxy_size = proxy_sizes[i];
				if (proxy_size & built_proxies) {
					char filename[FILE_MAX];
					get_proxy_filename(anim, proxy_size, filename, false);
					printf("Skipping proxy: %s\n", filename);
				}
			}
		}
		proxy_sizes_to_build &= ~built_proxies;
	}
	
	fflush(stdout);

	if (proxy_sizes_to_build == 0) {
		return NULL;
	}
	

	switch (anim->curtype) {
#ifdef WITH_FFMPEG
		case ANIM_FFMPEG:
			context = index_ffmpeg_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
			break;
#endif
#ifdef WITH_AVI
		default:
			context = index_fallback_create_context(anim, tcs_in_use, proxy_sizes_to_build, quality);
			break;
#endif
	}

	if (context)
		context->anim_type = anim->curtype;

	return context;

	UNUSED_VARS(tcs_in_use, proxy_sizes_in_use, quality);
}