use BLI_strncpy and BLI_snprintf when the size of the string is known.
[blender-staging.git] / source / blender / imbuf / intern / anim_movie.c
index 3adb9a3791fb2ba3ef0b8dfedc5ee55c1c0b53dd..a09033795285aa2dd88833ebad666ab80794833d 100644 (file)
 #endif
 #endif
 
-int ismovie(const char *UNUSED(filepath)) {
+int ismovie(const char *UNUSED(filepath))
+{
        return 0;
 }
 
@@ -126,7 +127,8 @@ static void free_anim_movie(struct anim *UNUSED(anim)) { ; }
 # define PATHSEPERATOR '/'
 #endif
 
-static int an_stringdec(const char *string, char* head, char *tail, unsigned short *numlen) {
+static int an_stringdec(const char *string, char* head, char *tail, unsigned short *numlen)
+{
        unsigned short len,nume,nums=0;
        short i,found=FALSE;
 
@@ -161,11 +163,13 @@ static int an_stringdec(const char *string, char* head, char *tail, unsigned sho
 }
 
 
-static void an_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic) {
+static void an_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
+{
        BLI_stringenc(string, head, tail, numlen, pic);
 }
 
-static void free_anim_avi (struct anim *anim) {
+static void free_anim_avi (struct anim *anim)
+{
 #if defined(_WIN32) && !defined(FREE_WINDOWS)
        int i;
 #endif
@@ -206,7 +210,8 @@ static void free_anim_ffmpeg(struct anim * anim);
 static void free_anim_redcode(struct anim * anim);
 #endif
 
-void IMB_free_anim(struct anim * anim) {
+void IMB_free_anim(struct anim * anim)
+{
        if (anim == NULL) {
                printf("free anim, anim == NULL\n");
                return;
@@ -229,14 +234,16 @@ void IMB_free_anim(struct anim * anim) {
        MEM_freeN(anim);
 }
 
-void IMB_close_anim(struct anim * anim) {
+void IMB_close_anim(struct anim * anim)
+{
        if (anim == NULL) return;
 
        IMB_free_anim(anim);
 }
 
 
-struct anim * IMB_open_anim( const char * name, int ib_flags, int streamindex) {
+struct anim * IMB_open_anim( const char * name, int ib_flags, int streamindex)
+{
        struct anim * anim;
 
        anim = (struct anim*)MEM_callocN(sizeof(struct anim), "anim struct");
@@ -249,7 +256,8 @@ struct anim * IMB_open_anim( const char * name, int ib_flags, int streamindex) {
 }
 
 
-static int startavi (struct anim *anim) {
+static int startavi (struct anim *anim)
+{
 
        AviError avierror;
 #if defined(_WIN32) && !defined(FREE_WINDOWS)
@@ -355,7 +363,8 @@ static int startavi (struct anim *anim) {
        return 0;
 }
 
-static ImBuf * avi_fetchibuf (struct anim *anim, int position) {
+static ImBuf * avi_fetchibuf (struct anim *anim, int position)
+{
        ImBuf *ibuf = NULL;
        int *tmp;
        int y;
@@ -405,7 +414,8 @@ static ImBuf * avi_fetchibuf (struct anim *anim, int position) {
 
 extern void do_init_ffmpeg(void);
 
-static int startffmpeg(struct anim * anim) {
+static int startffmpeg(struct anim * anim)
+{
        int            i, videoStream;
 
        AVCodec *pCodec;
@@ -504,7 +514,6 @@ static int startffmpeg(struct anim * anim) {
        anim->last_frame = 0;
        anim->last_pts = -1;
        anim->next_pts = -1;
-       anim->next_undecoded_pts = -1;
        anim->next_packet.stream_index = -1;
 
        anim->pFormatCtx = pFormatCtx;
@@ -513,6 +522,7 @@ static int startffmpeg(struct anim * anim) {
        anim->videoStream = videoStream;
 
        anim->pFrame = avcodec_alloc_frame();
+       anim->pFrameComplete = FALSE;
        anim->pFrameDeinterlaced = avcodec_alloc_frame();
        anim->pFrameRGB = avcodec_alloc_frame();
 
@@ -530,12 +540,12 @@ static int startffmpeg(struct anim * anim) {
        }
 
        if (anim->ib_flags & IB_animdeinterlace) {
-               avpicture_fill((AVPicture*) anim->pFrameDeinterlaced, 
-                                  MEM_callocN(avpicture_get_size(
-                                                  anim->pCodecCtx->pix_fmt,
-                                                  anim->x, anim->y), 
-                                          "ffmpeg deinterlace"), 
-                                  anim->pCodecCtx->pix_fmt, anim->x, anim->y);
+               avpicture_fill((AVPicture*) anim->pFrameDeinterlaced,
+                              MEM_callocN(avpicture_get_size(
+                                              anim->pCodecCtx->pix_fmt,
+                                              anim->x, anim->y),
+                                          "ffmpeg deinterlace"),
+                              anim->pCodecCtx->pix_fmt, anim->x, anim->y);
        }
 
        if (pCodecCtx->has_b_frames) {
@@ -602,6 +612,10 @@ static void ffmpeg_postprocess(struct anim * anim)
 
        ibuf->profile = IB_PROFILE_SRGB;
 
+       if (!anim->pFrameComplete) {
+               return;
+       }
+
        /* This means the data wasnt read properly, 
           this check stops crashing */
        if (input->data[0]==0 && input->data[1]==0 
@@ -611,6 +625,12 @@ static void ffmpeg_postprocess(struct anim * anim)
                return;
        }
 
+       av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
+              "  POSTPROC: anim->pFrame planes: %p %p %p %p\n",
+              input->data[0], input->data[1], input->data[2],
+              input->data[3]);
+
+
        if (anim->ib_flags & IB_animdeinterlace) {
                if (avpicture_deinterlace(
                            (AVPicture*) 
@@ -627,9 +647,9 @@ static void ffmpeg_postprocess(struct anim * anim)
                }
        }
        
-       avpicture_fill((AVPicture*) anim->pFrameRGB, 
-                      (unsigned char*) ibuf->rect, 
-                      PIX_FMT_RGBA, anim->x, anim->y);
+       avpicture_fill((AVPicture*) anim->pFrameRGB,
+                      (unsigned char*) ibuf->rect,
+                      PIX_FMT_RGBA, anim->x, anim->y);
 
        if (ENDIAN_ORDER == B_ENDIAN) {
                int * dstStride   = anim->pFrameRGB->linesize;
@@ -641,16 +661,12 @@ static void ffmpeg_postprocess(struct anim * anim)
                unsigned char* top;
                
                sws_scale(anim->img_convert_ctx,
-                         (const uint8_t * const *)input->data,
-                         input->linesize,
-                         0,
-                         anim->pCodecCtx->height,
-                         dst2,
-                         dstStride2);
-               
-               /* workaround: sws_scale bug
-                  sets alpha = 0 and compensate
-                  for altivec-bugs and flipy... */
+                         (const uint8_t * const *)input->data,
+                         input->linesize,
+                         0,
+                         anim->pCodecCtx->height,
+                         dst2,
+                         dstStride2);
                
                bottom = (unsigned char*) ibuf->rect;
                top = bottom + ibuf->x * (ibuf->y-1) * 4;
@@ -662,17 +678,17 @@ static void ffmpeg_postprocess(struct anim * anim)
                        unsigned char tmp[4];
                        unsigned int * tmp_l =
                                (unsigned int*) tmp;
-                       tmp[3] = 0xff;
                        
                        for (x = 0; x < w; x++) {
                                tmp[0] = bottom[0];
                                tmp[1] = bottom[1];
                                tmp[2] = bottom[2];
+                               tmp[3] = bottom[3];
                                
                                bottom[0] = top[0];
                                bottom[1] = top[1];
                                bottom[2] = top[2];
-                               bottom[3] = 0xff;
+                               bottom[3] = top[3];
                                
                                *(unsigned int*) top = *tmp_l;
                                
@@ -687,27 +703,14 @@ static void ffmpeg_postprocess(struct anim * anim)
                int dstStride2[4] = { -dstStride[0], 0, 0, 0 };
                uint8_t* dst2[4]  = { dst[0] + (anim->y - 1)*dstStride[0],
                                      0, 0, 0 };
-               int i;
-               unsigned char* r;
                
                sws_scale(anim->img_convert_ctx,
-                         (const uint8_t * const *)input->data,
-                         input->linesize,
-                         0,
-                         anim->pCodecCtx->height,
-                         dst2,
-                         dstStride2);
-               
-               r = (unsigned char*) ibuf->rect;
-               
-               /* workaround sws_scale bug: older version of 
-                  sws_scale set alpha = 0... */
-               if (r[3] == 0) {
-                       for (i = 0; i < ibuf->x * ibuf->y; i++) {
-                               r[3] = 0xff;
-                               r += 4;
-                       }
-               }
+                         (const uint8_t * const *)input->data,
+                         input->linesize,
+                         0,
+                         anim->pCodecCtx->height,
+                         dst2,
+                         dstStride2);
        }
 
        if (filter_y) {
@@ -715,40 +718,15 @@ static void ffmpeg_postprocess(struct anim * anim)
        }
 }
 
-/* decode one video frame and load the next packet into anim->packet,
-   so that we can obtain next_pts and next undecoded pts */
+/* decode one video frame also considering the packet read into next_packet */
 
 static int ffmpeg_decode_video_frame(struct anim * anim)
 {
-       int frameFinished = 0;
        int rval = 0;
 
        av_log(anim->pFormatCtx, AV_LOG_DEBUG, "  DECODE VIDEO FRAME\n");
 
-       anim->next_undecoded_pts = -1;
-
        if (anim->next_packet.stream_index == anim->videoStream) {
-               av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
-                      "  DECODE: cached next packet\n");
-
-               avcodec_decode_video2(anim->pCodecCtx, 
-                                     anim->pFrame, &frameFinished, 
-                                     &anim->next_packet);
-
-               if (frameFinished) {
-                       av_log(anim->pFormatCtx, 
-                              AV_LOG_DEBUG, 
-                              "  FRAME DONE: "
-                               "next_pts=%lld pkt_pts=%lld\n",
-                               (anim->pFrame->pts == AV_NOPTS_VALUE) ? 
-                               -1 : (long long int)anim->pFrame->pts,
-                               (anim->pFrame->pkt_pts == AV_NOPTS_VALUE) ?
-                               -1 : (long long int)anim->pFrame->pkt_pts);
-                       anim->next_pts = 
-                               av_get_pts_from_frame(anim->pFormatCtx,
-                                                     anim->pFrame);
-               }
-
                av_free_packet(&anim->next_packet);
                anim->next_packet.stream_index = -1;
        }
@@ -769,21 +747,14 @@ static int ffmpeg_decode_video_frame(struct anim * anim)
                       (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? 
                       " KEY" : "");
                if (anim->next_packet.stream_index == anim->videoStream) {
-                       if (frameFinished) {
-                               av_log(anim->pFormatCtx,
-                                      AV_LOG_DEBUG,
-                                      "  FRAME finished, we leave\n");
-                               anim->next_undecoded_pts 
-                                       = anim->next_packet.dts;
-                               break;
-                       }
+                       anim->pFrameComplete = 0;
 
                        avcodec_decode_video2(
                                anim->pCodecCtx, 
-                               anim->pFrame, &frameFinished
+                               anim->pFrame, &anim->pFrameComplete
                                &anim->next_packet);
 
-                       if (frameFinished) {
+                       if (anim->pFrameComplete) {
                                anim->next_pts = av_get_pts_from_frame(
                                        anim->pFormatCtx, anim->pFrame);
 
@@ -797,6 +768,7 @@ static int ffmpeg_decode_video_frame(struct anim * anim)
                                        == AV_NOPTS_VALUE) ?
                                       -1 : (long long int)anim->pFrame->pkt_pts,
                                        (long long int)anim->next_pts);
+                               break;
                        }
                }
                av_free_packet(&anim->next_packet);
@@ -804,10 +776,13 @@ static int ffmpeg_decode_video_frame(struct anim * anim)
        }
        
        if (rval < 0) {
+               anim->next_packet.stream_index = -1;
+
                av_log(anim->pFormatCtx,
                       AV_LOG_ERROR, "  DECODE READ FAILED: av_read_frame() "
                       "returned error: %d\n",  rval);
        }
+
        return (rval >= 0);
 }
 
@@ -870,7 +845,7 @@ static int match_format(const char *name, AVFormatContext * pFormatCtx)
 
 static int ffmpeg_seek_by_byte(AVFormatContext *pFormatCtx)
 {
-       static const char * byte_seek_list [] = { "dv", "mpegts", 0 };
+       static const char * byte_seek_list [] = { "mpegts", 0 };
        const char ** p;
 
        if (pFormatCtx->iformat->flags & AVFMT_TS_DISCONT) {
@@ -923,7 +898,8 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
                        tc_index, new_frame_index);
        } else {
                pts_to_search = (long long) 
-                       floor(((double) position) / pts_time_base / frame_rate + 0.5);
+                       floor(((double) position) 
+                             / pts_time_base / frame_rate + 0.5);
 
                if (st_time != AV_NOPTS_VALUE) {
                        pts_to_search += st_time / pts_time_base 
@@ -934,35 +910,23 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
        av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
               "FETCH: looking for PTS=%lld "
               "(pts_timebase=%g, frame_rate=%g, st_time=%lld)\n", 
-              (long long int)pts_to_search, pts_time_base, frame_rate, st_time);
+              (long long int)pts_to_search,pts_time_base, frame_rate, st_time);
 
        if (anim->last_frame && 
            anim->last_pts <= pts_to_search && anim->next_pts > pts_to_search){
                av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
                       "FETCH: frame repeat: last: %lld next: %lld\n",
-                      (long long int)anim->last_pts, (long long int)anim->next_pts);
+                      (long long int)anim->last_pts, 
+                      (long long int)anim->next_pts);
                IMB_refImBuf(anim->last_frame);
                anim->curposition = position;
                return anim->last_frame;
        }
         
-       IMB_freeImBuf(anim->last_frame);
-
-       if (anim->next_pts <= pts_to_search && 
-           anim->next_undecoded_pts > pts_to_search) {
-               av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
-                      "FETCH: no seek necessary: "
-                       "next: %lld next undecoded: %lld\n",
-                       (long long int)anim->next_pts,
-                   (long long int)anim->next_undecoded_pts);
-
-               /* we are already done :) */
-
-       } else if (position > anim->curposition + 1 
-                  && anim->preseek 
-                  && !tc_index
-                  && position - (anim->curposition + 1) < anim->preseek) {
-
+       if (position > anim->curposition + 1 
+           && anim->preseek 
+           && !tc_index
+           && position - (anim->curposition + 1) < anim->preseek) {
                av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
                       "FETCH: within preseek interval (no index)\n");
 
@@ -1011,6 +975,11 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
                } else {
                        pos = (long long) (position - anim->preseek) 
                                * AV_TIME_BASE / frame_rate;
+
+                       av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
+                              "NO INDEX seek pos = %lld, st_time = %lld\n", 
+                              pos, (st_time != AV_NOPTS_VALUE) ? st_time : 0);
+
                        if (pos < 0) {
                                pos = 0;
                        }
@@ -1019,15 +988,18 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
                                pos += st_time;
                        }
 
+                       av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
+                              "NO INDEX final seek pos = %lld\n", pos);
+
                        ret = av_seek_frame(anim->pFormatCtx, -1, 
                                            pos, AVSEEK_FLAG_BACKWARD);
                }
 
                if (ret < 0) {
-                       av_log(anim->pFormatCtx, AV_LOG_ERROR, 
+                       av_log(anim->pFormatCtx, AV_LOG_ERROR,
                               "FETCH: "
                               "error while seeking to DTS = %lld "
-                              "(frameno = %d, PTS = %lld): errcode = %d\n", 
+                              "(frameno = %d, PTS = %lld): errcode = %d\n",
                               pos, position, (long long int)pts_to_search, ret);
                }
 
@@ -1048,12 +1020,16 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
        } else if (position == 0 && anim->curposition == -1) {
                /* first frame without seeking special case... */
                ffmpeg_decode_video_frame(anim);
+       } else {
+               av_log(anim->pFormatCtx, AV_LOG_DEBUG, 
+                      "FETCH: no seek necessary, just continue...\n");
        }
 
+       IMB_freeImBuf(anim->last_frame);
        anim->last_frame = IMB_allocImBuf(anim->x, anim->y, 32, IB_rect);
 
        ffmpeg_postprocess(anim);
-       
+
        anim->last_pts = anim->next_pts;
        
        ffmpeg_decode_video_frame(anim);
@@ -1061,11 +1037,12 @@ static ImBuf * ffmpeg_fetchibuf(struct anim * anim, int position,
        anim->curposition = position;
        
        IMB_refImBuf(anim->last_frame);
-       
+
        return anim->last_frame;
 }
 
-static void free_anim_ffmpeg(struct anim * anim) {
+static void free_anim_ffmpeg(struct anim * anim)
+{
        if (anim == NULL) return;
 
        if (anim->pCodecCtx) {
@@ -1091,7 +1068,8 @@ static void free_anim_ffmpeg(struct anim * anim) {
 
 #ifdef WITH_REDCODE
 
-static int startredcode(struct anim * anim) {
+static int startredcode(struct anim * anim)
+{
        anim->redcodeCtx = redcode_open(anim->name);
        if (!anim->redcodeCtx) {
                return -1;
@@ -1101,7 +1079,8 @@ static int startredcode(struct anim * anim) {
        return 0;
 }
 
-static ImBuf * redcode_fetchibuf(struct anim * anim, int position) {
+static ImBuf * redcode_fetchibuf(struct anim * anim, int position)
+{
        struct ImBuf * ibuf;
        struct redcode_frame * frame;
        struct redcode_frame_raw * raw_frame;
@@ -1125,14 +1104,15 @@ static ImBuf * redcode_fetchibuf(struct anim * anim, int position) {
        }
        
                ibuf = IMB_allocImBuf(raw_frame->width * 2, 
-                                 raw_frame->height * 2, 32, IB_rectfloat);
+                                     raw_frame->height * 2, 32, IB_rectfloat);
 
        redcode_decode_video_float(raw_frame, ibuf->rect_float, 1);
 
        return ibuf;
 }
 
-static void free_anim_redcode(struct anim * anim) {
+static void free_anim_redcode(struct anim * anim)
+{
        if (anim->redcodeCtx) {
                redcode_close(anim->redcodeCtx);
                anim->redcodeCtx = 0;
@@ -1146,7 +1126,8 @@ static void free_anim_redcode(struct anim * anim) {
 /* Geen plaatje, probeer dan volgende animatie te openen */
 /* gelukt, haal dan eerste plaatje van animatie */
 
-static struct ImBuf * anim_getnew(struct anim * anim) {
+static struct ImBuf * anim_getnew(struct anim * anim)
+{
        struct ImBuf *ibuf = NULL;
 
        if (anim == NULL) return(NULL);
@@ -1208,7 +1189,8 @@ static struct ImBuf * anim_getnew(struct anim * anim) {
        return(ibuf);
 }
 
-struct ImBuf * IMB_anim_previewframe(struct anim * anim) {
+struct ImBuf * IMB_anim_previewframe(struct anim * anim)
+{
        struct ImBuf * ibuf = NULL;
        int position = 0;
        
@@ -1307,7 +1289,7 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position,
 
        if (ibuf) {
                if (filter_y) IMB_filtery(ibuf);
-               sprintf(ibuf->name, "%s.%04d", anim->name, anim->curposition + 1);
+               BLI_snprintf(ibuf->name, sizeof(ibuf->name), "%s.%04d", anim->name, anim->curposition + 1);
                
        }
        return(ibuf);
@@ -1315,7 +1297,8 @@ struct ImBuf * IMB_anim_absolute(struct anim * anim, int position,
 
 /***/
 
-int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc) {
+int IMB_anim_get_duration(struct anim *anim, IMB_Timecode_Type tc)
+{
        struct anim_index * idx;
        if (tc == IMB_TC_NONE) {
                return anim->duration;