style cleanup: comment blocks
[blender.git] / source / blender / imbuf / intern / indexer.c
index 8b2e27ae1f3dc10ac1c4f4e37f755f91960d6916..f35a4345366ec2d9713138b1959bc9f1527cbbf9 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
-#include "IMB_indexer.h"
-#include "IMB_anim.h"
-#include "AVI_avi.h"
-#include "imbuf.h"
+#include <stdlib.h>
+
 #include "MEM_guardedalloc.h"
 
 #include "BLI_utildefines.h"
-#include "BLI_blenlib.h"
+#include "BLI_endian_switch.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_path_util.h"
+#include "BLI_fileops.h"
 #include "BLI_math_base.h"
 
+#include "IMB_indexer.h"
+#include "IMB_anim.h"
+#include "AVI_avi.h"
+#include "imbuf.h"
+
 #include "MEM_guardedalloc.h"
 #include "DNA_userdef_types.h"
 #include "BKE_global.h"
-#include <stdlib.h>
 
 #ifdef WITH_FFMPEG
 
@@ -181,12 +187,12 @@ struct anim_index *IMB_indexer_open(const char *name)
        fseek(fp, 0, SEEK_END);
 
        idx->num_entries = (ftell(fp) - 12) /
-                          (sizeof(int) + // framepos
-                           sizeof(unsigned long long) + // seek_pos
-                           sizeof(unsigned long long) + // seek_pos_dts
-                           sizeof(unsigned long long) // pts
+                          (sizeof(int) +                /* framepos */
+                           sizeof(unsigned long long) + /* seek_pos */
+                           sizeof(unsigned long long) + /* seek_pos_dts */
+                           sizeof(unsigned long long)   /* pts */
                           );
-       
+
        fseek(fp, 12, SEEK_SET);
 
        idx->entries = MEM_callocN(sizeof(struct anim_index_entry) *
@@ -205,10 +211,10 @@ struct anim_index *IMB_indexer_open(const char *name)
 
        if (((ENDIAN_ORDER == B_ENDIAN) != (header[8] == 'V'))) {
                for (i = 0; i < idx->num_entries; i++) {
-                       SWITCH_INT(idx->entries[i].frameno);
-                       SWITCH_INT64(idx->entries[i].seek_pos);
-                       SWITCH_INT64(idx->entries[i].seek_pos_dts);
-                       SWITCH_INT64(idx->entries[i].pts);
+                       BLI_endian_switch_int32(&idx->entries[i].frameno);
+                       BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos);
+                       BLI_endian_switch_int64((int64_t *)&idx->entries[i].seek_pos_dts);
+                       BLI_endian_switch_int64((int64_t *)&idx->entries[i].pts);
                }
        }
 
@@ -218,7 +224,7 @@ struct anim_index *IMB_indexer_open(const char *name)
 }
 
 unsigned long long IMB_indexer_get_seek_pos(
-    struct anim_index *idx, int frame_index)
+        struct anim_index *idx, int frame_index)
 {
        if (frame_index < 0) {
                frame_index = 0;
@@ -230,7 +236,7 @@ unsigned long long IMB_indexer_get_seek_pos(
 }
 
 unsigned long long IMB_indexer_get_seek_pos_dts(
-    struct anim_index *idx, int frame_index)
+        struct anim_index *idx, int frame_index)
 {
        if (frame_index < 0) {
                frame_index = 0;
@@ -472,7 +478,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
        char fname[FILE_MAX];
        int ffmpeg_quality;
 
-       // JPEG requires this
+       /* JPEG requires this */
        width = round_up(width, 8);
        height = round_up(height, 8);
 
@@ -578,7 +584,7 @@ static struct proxy_output_ctx *alloc_proxy_output_ffmpeg(
 }
 
 static int add_to_proxy_output_ffmpeg(
-    struct proxy_output_ctx *ctx, AVFrame *frame)
+        struct proxy_output_ctx *ctx, AVFrame *frame)
 {
        int outsize = 0;
 
@@ -717,6 +723,17 @@ typedef struct FFmpegIndexBuilderContext {
 
        IMB_Timecode_Type tcs_in_use;
        IMB_Proxy_Size proxy_sizes_in_use;
+
+       unsigned long long seek_pos;
+       unsigned long long last_seek_pos;
+       unsigned long long seek_pos_dts;
+       unsigned long long seek_pos_pts;
+       unsigned long long last_seek_pos_dts;
+       unsigned long long start_pts;
+       double frame_rate;
+       double pts_time_base;
+       int frameno, frameno_gapless;
+       int start_pts_set;
 } FFmpegIndexBuilderContext;
 
 static IndexBuildContext *index_ffmpeg_create_context(struct anim *anim, IMB_Timecode_Type tcs_in_use,
@@ -833,20 +850,63 @@ static void index_rebuild_ffmpeg_finish(FFmpegIndexBuilderContext *context, int
        MEM_freeN(context);
 }
 
+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.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 < 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++;
+}
+
 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;
@@ -855,8 +915,8 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
 
        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);
+       context->frame_rate = av_q2d(context->iStream->r_frame_rate);
+       context->pts_time_base = av_q2d(context->iStream->time_base);
 
        while (av_read_frame(context->iFormatCtx, &next_packet) >= 0) {
                int frame_finished = 0;
@@ -875,11 +935,11 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
 
                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;
+                               context->last_seek_pos = context->seek_pos;
+                               context->last_seek_pos_dts = context->seek_pos_dts;
+                               context->seek_pos = next_packet.pos;
+                               context->seek_pos_dts = next_packet.dts;
+                               context->seek_pos_pts = next_packet.pts;
                        }
 
                        avcodec_decode_video2(
@@ -888,54 +948,34 @@ static int index_rebuild_ffmpeg(FFmpegIndexBuilderContext *context,
                }
 
                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);
+                       index_rebuild_ffmpeg_proc_decoded_frame(
+                               context, &next_packet, in_frame);
+               }
+               av_free_packet(&next_packet);
+       }
 
-                       /* 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 */
+       /* process pictures still stuck in decoder engine after EOF
+        * according to ffmpeg docs using 0-size packets.
+        *
+        * At least, if we haven't already stopped... */
+       if (!*stop) {
+               int frame_finished;
 
-                       if (pts < seek_pos_pts) {
-                               s_pos = last_seek_pos;
-                               s_dts = last_seek_pos_dts;
-                       }
+               next_packet.size = 0;
+               next_packet.data = 0;
 
-                       for (i = 0; i < context->num_indexers; i++) {
-                               if (context->tcs_in_use & tc_types[i]) {
-                                       int tc_frameno = frameno;
+               do {
+                       frame_finished = 0;
 
-                                       if (tc_types[i] == IMB_TC_RECORD_RUN_NO_GAPS)
-                                               tc_frameno = frameno_gapless;
+                       avcodec_decode_video2(
+                               context->iCodecCtx, in_frame, &frame_finished,
+                               &next_packet);
 
-                                       IMB_index_builder_proc_frame(
-                                               context->indexer[i],
-                                               next_packet.data,
-                                               next_packet.size,
-                                               tc_frameno,
-                                               s_pos, s_dts, pts);
-                               }
+                       if (frame_finished) {
+                               index_rebuild_ffmpeg_proc_decoded_frame(
+                                       context, &next_packet, in_frame);
                        }
-
-                       frameno_gapless++;
-               }
-               av_free_packet(&next_packet);
+               } while (frame_finished);
        }
 
        av_free(in_frame);
@@ -1214,7 +1254,8 @@ struct anim *IMB_anim_open_proxy(
 
        get_proxy_filename(anim, preview_size, fname, FALSE);
 
-       anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0);
+       /* proxies are generated in default color space */
+       anim->proxy_anim[i] = IMB_open_anim(fname, 0, 0, NULL);
        
        anim->proxies_tried |= preview_size;