Пример #1
0
static void index_rebuild_ffmpeg_proc_decoded_frame(
	FFmpegIndexBuilderContext *context, 
	AVPacket * curr_packet,
	AVFrame *in_frame)
{
	int i;
	unsigned long long s_pos = context->seek_pos;
	unsigned long long s_dts = context->seek_pos_dts;
	unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame);

	for (i = 0; i < context->num_proxy_sizes; i++) {
		add_to_proxy_output_ffmpeg(context->proxy_ctx[i], in_frame);
	}

	if (!context->start_pts_set) {
		context->start_pts = pts;
		context->start_pts_set = TRUE;
	}

	context->frameno = floor((pts - context->start_pts) *
	                         context->pts_time_base  *
	                         context->frame_rate + 0.5);

	/* decoding starts *always* on I-Frames,
	 * so: P-Frames won't work, even if all the
	 * information is in place, when we seek
	 * to the I-Frame presented *after* the P-Frame,
	 * but located before the P-Frame within
	 * the stream */

	if (pts < context->seek_pos_pts) {
		s_pos = context->last_seek_pos;
		s_dts = context->last_seek_pos_dts;
	}

	for (i = 0; i < context->num_indexers; i++) {
		if (context->tcs_in_use & tc_types[i]) {
			int tc_frameno = context->frameno;

			if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS)
				tc_frameno = context->frameno_gapless;
			
			IMB_index_builder_proc_frame(
				context->indexer[i],
				curr_packet->data,
				curr_packet->size,
				tc_frameno,
				s_pos, s_dts, pts);
		}
	}
	
	context->frameno_gapless++;
}
Пример #2
0
static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
                                short *stop, short *do_update, float *progress)
{
	int i;
	unsigned long long seek_pos = 0;
	unsigned long long last_seek_pos = 0;
	unsigned long long seek_pos_dts = 0;
	unsigned long long seek_pos_pts = 0;
	unsigned long long last_seek_pos_dts = 0;
	unsigned long long start_pts = 0;
	double frame_rate;
	double pts_time_base;
	int frameno = 0, frameno_gapless = 0;
	int start_pts_set = FALSE;
	AVFrame *in_frame = 0;
	AVPacket next_packet;
	uint64_t stream_size;

	in_frame = avcodec_alloc_frame();

	stream_size = avio_size(context->iFormatCtx->pb);

	frame_rate = av_q2d(context->iStream->r_frame_rate);
	pts_time_base = av_q2d(context->iStream->time_base);

	while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) {
		int frame_finished = 0;
		float next_progress =  (float)((int)floor(((double) next_packet.pos) * 100 /
		                                          ((double) stream_size) + 0.5)) / 100;

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

		if (*stop) {
			av_free_packet(&next_packet);
			break;
		}

		if (next_packet.stream_index == context->videoStream) {
			if (next_packet.flags & AV_PKT_FLAG_KEY) {
				last_seek_pos = seek_pos;
				last_seek_pos_dts = seek_pos_dts;
				seek_pos = next_packet.pos;
				seek_pos_dts = next_packet.dts;
				seek_pos_pts = next_packet.pts;
			}

			avcodec_decode_video2(
			        context->iCodecCtx, in_frame, &frame_finished,
			        &next_packet);
		}

		if (frame_finished) {
			unsigned long long s_pos = seek_pos;
			unsigned long long s_dts = seek_pos_dts;
			unsigned long long pts = av_get_pts_from_frame(context->iFormatCtx, in_frame);

			for (i = 0; i < context->num_proxy_sizes; i++) {
				add_to_proxy_output_ffmpeg(
				        context->proxy_ctx[i], in_frame);
			}

			if (!start_pts_set) {
				start_pts = pts;
				start_pts_set = TRUE;
			}

			frameno = floor((pts - start_pts) *
			                pts_time_base * frame_rate + 0.5f);

			/* decoding starts *always* on I-Frames,
			 * so: P-Frames won't work, even if all the
			 * information is in place, when we seek
			 * to the I-Frame presented *after* the P-Frame,
			 * but located before the P-Frame within
			 * the stream */

			if (pts < seek_pos_pts) {
				s_pos = last_seek_pos;
				s_dts = last_seek_pos_dts;
			}

			for (i = 0; i < context->num_indexers; i++) {
				if (context->tcs_in_use & tc_types[i]) {
					int tc_frameno = frameno;

					if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS)
						tc_frameno = frameno_gapless;

					IMB_index_builder_proc_frame(
					        context->indexer[i],
					        next_packet.data,
					        next_packet.size,
					        tc_frameno,
					        s_pos, s_dts, pts);
				}
			}

			frameno_gapless++;
		}
		av_free_packet(&next_packet);
	}

	av_free(in_frame);

	return 1;
}
Пример #3
0
static int index_rebuild_ffmpeg(struct anim * anim,
                                IMB_Timecode_Type tcs_in_use,
                                IMB_Proxy_Size proxy_sizes_in_use,
                                int quality,
                                short *stop, short *do_update,
                                float *progress)
{
    int i, videoStream;
    unsigned long long seek_pos = 0;
    unsigned long long last_seek_pos = 0;
    unsigned long long seek_pos_dts = 0;
    unsigned long long seek_pos_pts = 0;
    unsigned long long last_seek_pos_dts = 0;
    unsigned long long start_pts = 0;
    double frame_rate;
    double pts_time_base;
    int frameno = 0;
    int start_pts_set = FALSE;

    AVFormatContext *iFormatCtx;
    AVCodecContext *iCodecCtx;
    AVCodec *iCodec;
    AVStream *iStream;
    AVFrame* in_frame = 0;
    AVPacket next_packet;
    int streamcount;

    struct proxy_output_ctx * proxy_ctx[IMB_PROXY_MAX_SLOT];
    anim_index_builder * indexer [IMB_TC_MAX_SLOT];

    int num_proxy_sizes = IMB_PROXY_MAX_SLOT;
    int num_indexers = IMB_TC_MAX_SLOT;
    uint64_t stream_size;

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

    if(av_open_input_file(&iFormatCtx, anim->name, NULL, 0, NULL) != 0) {
        return 0;
    }

    if (av_find_stream_info(iFormatCtx) < 0) {
        av_close_input_file(iFormatCtx);
        return 0;
    }

    streamcount = anim->streamindex;

    /* Find the video stream */
    videoStream = -1;
    for (i = 0; i < iFormatCtx->nb_streams; i++)
        if(iFormatCtx->streams[i]->codec->codec_type
                == AVMEDIA_TYPE_VIDEO) {
            if (streamcount > 0) {
                streamcount--;
                continue;
            }
            videoStream = i;
            break;
        }

    if (videoStream == -1) {
        av_close_input_file(iFormatCtx);
        return 0;
    }

    iStream = iFormatCtx->streams[videoStream];
    iCodecCtx = iStream->codec;

    iCodec = avcodec_find_decoder(iCodecCtx->codec_id);

    if (iCodec == NULL) {
        av_close_input_file(iFormatCtx);
        return 0;
    }

    iCodecCtx->workaround_bugs = 1;

    if (avcodec_open(iCodecCtx, iCodec) < 0) {
        av_close_input_file(iFormatCtx);
        return 0;
    }

    in_frame = avcodec_alloc_frame();

    stream_size = avio_size(iFormatCtx->pb);

    for (i = 0; i < num_proxy_sizes; i++) {
        if (proxy_sizes_in_use & proxy_sizes[i]) {
            proxy_ctx[i] = alloc_proxy_output_ffmpeg(
                               anim, iStream, proxy_sizes[i],
                               iCodecCtx->width * proxy_fac[i],
                               iCodecCtx->height * proxy_fac[i],
                               quality);
            if (!proxy_ctx[i]) {
                proxy_sizes_in_use &= ~proxy_sizes[i];
            }
        }
    }

    for (i = 0; i < num_indexers; i++) {
        if (tcs_in_use & tc_types[i]) {
            char fname[FILE_MAXDIR+FILE_MAXFILE];

            get_tc_filename(anim, tc_types[i], fname);

            indexer[i] = IMB_index_builder_create(fname);
            if (!indexer[i]) {
                tcs_in_use &= ~tc_types[i];
            }
        }
    }

    frame_rate = av_q2d(iStream->r_frame_rate);
    pts_time_base = av_q2d(iStream->time_base);

    while(av_read_frame(iFormatCtx, &next_packet) >= 0) {
        int frame_finished = 0;
        float next_progress =  ((int)floor(((double) next_packet.pos) * 100 /
                                           ((double) stream_size)+0.5)) / 100;

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

        if (*stop) {
            av_free_packet(&next_packet);
            break;
        }

        if (next_packet.stream_index == videoStream) {
            if (next_packet.flags & AV_PKT_FLAG_KEY) {
                last_seek_pos = seek_pos;
                last_seek_pos_dts = seek_pos_dts;
                seek_pos = next_packet.pos;
                seek_pos_dts = next_packet.dts;
                seek_pos_pts = next_packet.pts;
            }

            avcodec_decode_video2(
                iCodecCtx, in_frame, &frame_finished,
                &next_packet);
        }

        if (frame_finished) {
            unsigned long long s_pos = seek_pos;
            unsigned long long s_dts = seek_pos_dts;
            unsigned long long pts
                = av_get_pts_from_frame(iFormatCtx, in_frame);

            for (i = 0; i < num_proxy_sizes; i++) {
                add_to_proxy_output_ffmpeg(
                    proxy_ctx[i], in_frame);
            }

            if (!start_pts_set) {
                start_pts = pts;
                start_pts_set = TRUE;
            }

            frameno = (pts - start_pts)
                      * pts_time_base * frame_rate;

            /* decoding starts *always* on I-Frames,
               so: P-Frames won't work, even if all the
               information is in place, when we seek
               to the I-Frame presented *after* the P-Frame,
               but located before the P-Frame within
               the stream */

            if (pts < seek_pos_pts) {
                s_pos = last_seek_pos;
                s_dts = last_seek_pos_dts;
            }

            for (i = 0; i < num_indexers; i++) {
                if (tcs_in_use & tc_types[i]) {
                    IMB_index_builder_proc_frame(
                        indexer[i],
                        next_packet.data,
                        next_packet.size,
                        frameno, s_pos,	s_dts, pts);
                }
            }
        }
        av_free_packet(&next_packet);
    }

    for (i = 0; i < num_indexers; i++) {
        if (tcs_in_use & tc_types[i]) {
            IMB_index_builder_finish(indexer[i], *stop);
        }
    }

    for (i = 0; i < num_proxy_sizes; i++) {
        if (proxy_sizes_in_use & proxy_sizes[i]) {
            free_proxy_output_ffmpeg(proxy_ctx[i], *stop);
        }
    }

    av_free(in_frame);

    return 1;
}