Improve '__mmfile_get_frame' function to reduce Cyclomatic Complexity 18/213618/2 accepted/tizen/unified/20190910.043227 submit/tizen/20190910.020543
authorjiyong.min <jiyong.min@samsung.com>
Mon, 9 Sep 2019 07:28:09 +0000 (16:28 +0900)
committerjiyong.min <jiyong.min@samsung.com>
Mon, 9 Sep 2019 07:48:30 +0000 (16:48 +0900)
Change-Id: Ia0335b309420605b39dadef3b63c114e94f2564d

formats/ffmpeg/mm_file_format_frame.c

index 7e42462..a0ae37b 100755 (executable)
@@ -32,9 +32,9 @@
 
 #define MILLION 1000000
 #ifdef MMFILE_FORMAT_DEBUG_DUMP
-static void __save_frame(uint8_t *const dst[], const int dstStride[], int width, int height, int iFrame);
+static void __save_frame(int width, int height, unsigned char *frame, int size, int iFrame);
 
-void __save_frame(uint8_t *const dst[], const int dstStride[], int width, int height, int iFrame)
+void __save_frame(int width, int height, unsigned char *frame, int size, int iFrame)
 {
        FILE *pFile;
        char szFilename[32] = {0,};
@@ -50,8 +50,7 @@ void __save_frame(uint8_t *const dst[], const int dstStride[], int width, int he
        /* Write header */
        fprintf(pFile, "P6\n%d %d\n255\n", width, height);
        /* Write pixel data */
-       for (y = 0; y < height; y++)
-               fwrite(dst[0] + y * dstStride[0], 1, width * 3, pFile);
+       fwrite(frame, 1, size, pFile);
 
        /* Close file */
        fclose(pFile);
@@ -279,77 +278,57 @@ FILE_FORMAT_SUCCESS:
        return MMFILE_FORMAT_SUCCESS;
 }
 
-static int __mmfile_get_frame(AVFormatContext *pFormatCtx, int64_t timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
+static int __mmfile_get_first_video_stream(AVFormatContext *pFormatCtx, int *videoStream)
 {
        unsigned int i = 0;
-       int len = 0;
-       int ret = MMFILE_FORMAT_SUCCESS;
-       int videoStream = -1;
-       int64_t pos = timestamp;
-       bool find = false;
-       bool first_seek = true;
-       int64_t pts = 0;
-       AVCodecContext *pVideoCodecCtx = NULL;
-       AVCodecParameters *pVideoCodecPar = NULL;
-       AVCodec *pVideoCodec = NULL;
-       AVFrame *pFrame = NULL;
-       AVPacket packet;
-       AVStream *pStream = NULL;
-       double duration = 0;
-       int64_t tmpPts = 0;
-#ifdef __MMFILE_TEST_MODE__
-       int idx = 0;
-#endif
 
-       /* Retrieve stream information */
-       if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
-               debug_error(DEBUG, "error : av_find_stream_info failed");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception; /* Couldn't find stream information */
-       }
+       *videoStream = -1;
 
        /* Find the first video stream */
        for (i = 0; i < pFormatCtx->nb_streams; i++) {
                if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
-                       videoStream = i;
+                       *videoStream = i;
                        break;
                }
        }
 
-       if (videoStream == -1) {
+       if (*videoStream == -1) {
                debug_error(DEBUG, "error : videoStream == -1");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception; /* Didn't find a video stream */
+               return MMFILE_FORMAT_FAIL;
        }
 
+       return MMFILE_FORMAT_SUCCESS;
+}
+
+static int __mmfile_open_video_codec(AVFormatContext *pFormatCtx, int videoStream, AVCodecContext **ppVideoCodecCtx)
+{
+       AVCodecContext *pVideoCodecCtx = NULL;
+       AVCodecParameters *pVideoCodecPar = NULL;
+       AVCodec *pVideoCodec = NULL;
+
        /* Get a pointer to the codec context for the video stream */
        pVideoCodecPar = pFormatCtx->streams[videoStream]->codecpar;
-       if (pVideoCodecPar == NULL) {
+       if (!pVideoCodecPar) {
                debug_error(DEBUG, "invalid param\n");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception;
+               return MMFILE_FORMAT_FAIL;
        }
 
        /* Find the decoder for the video stream */
        pVideoCodec = avcodec_find_decoder(pVideoCodecPar->codec_id);
-       if (pVideoCodec == NULL) {
+       if (!pVideoCodec) {
                debug_error(DEBUG, "error : Unsupported codec");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception; /* Codec not found */
+               return MMFILE_FORMAT_FAIL;
        }
 
        pVideoCodecCtx = avcodec_alloc_context3(pVideoCodec);
-       if (NULL == pVideoCodecCtx) {
+       if (!pVideoCodecCtx) {
                debug_error(DEBUG, "error: pVideoCodecCtx == NULL\n");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception;
+               return MMFILE_FORMAT_FAIL;
        }
 
-       ret = avcodec_parameters_to_context(pVideoCodecCtx, pVideoCodecPar);
-       if (ret < 0) {
+       if (avcodec_parameters_to_context(pVideoCodecCtx, pVideoCodecPar) < 0) {
                debug_error(DEBUG, "error: avcodec_parameters_to_context\n");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception;
+               return MMFILE_FORMAT_FAIL;
        }
 
        /*set workaround bug flag*/
@@ -360,21 +339,18 @@ static int __mmfile_get_frame(AVFormatContext *pFormatCtx, int64_t timestamp, bo
        pVideoCodecCtx->thread_count = 0;
        if (avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0) {
                debug_error(DEBUG, "error : avcodec_open failed");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception;; /*Could not open codec */
+               return MMFILE_FORMAT_FAIL;
        }
 
-       /* Storing Data  */
-       /* Allocate video frame */
-       pFrame = av_frame_alloc();
-       if (pFrame == NULL) {
-               debug_error(DEBUG, "error: pFrame is NULL\n");
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception;
-       }
+       *ppVideoCodecCtx = pVideoCodecCtx;
+
+       return MMFILE_FORMAT_SUCCESS;
+}
+
+static int __mmfile_seek_to_pos(AVFormatContext *pFormatCtx, int64_t pos, bool is_accurate)
+{
+       double duration = 0;
 
-       /* Seeking */
-       pStream = pFormatCtx->streams[videoStream];
        duration = (double) pFormatCtx->duration / AV_TIME_BASE;
 #if 0
        if (duration <= 0) {
@@ -392,8 +368,7 @@ static int __mmfile_get_frame(AVFormatContext *pFormatCtx, int64_t timestamp, bo
        duration = duration * MILLION;
        if ((duration <= 0) || (duration <= pos)) {
                debug_error(DEBUG, "duration error duration[%f] pos[%"PRId64"]", duration, pos);
-               ret = MMFILE_FORMAT_FAIL;
-               goto exception;
+               return MMFILE_FORMAT_FAIL;
        }
 
        if (is_accurate)
@@ -401,17 +376,32 @@ static int __mmfile_get_frame(AVFormatContext *pFormatCtx, int64_t timestamp, bo
        else
                av_seek_frame(pFormatCtx, -1, pos, AVSEEK_FLAG_BACKWARD);
 
-       /* Reading Data */
+       return MMFILE_FORMAT_SUCCESS;
+}
 
+static bool __mmfile_find_proper_frame(AVFormatContext *pFormatCtx, int videoStream, AVCodecContext *pVideoCodecCtx, int64_t pos, bool is_accurate, AVFrame *pFrame)
+{
+       bool find = false;
+       AVPacket packet;
+       AVStream *pStream = NULL;
+       bool first_seek = true;
+       int64_t pts = 0;
+       int64_t tmpPts = 0;
+       int len = 0;
+#ifdef __MMFILE_TEST_MODE__
+       int idx = 0;
+#endif
+
+       pStream = pFormatCtx->streams[videoStream];
        av_init_packet(&packet);
 
        while (av_read_frame(pFormatCtx, &packet) >= 0) {
 
                /* Is this a packet from the video stream? */
                if (packet.stream_index == videoStream) {
-                       #ifdef __MMFILE_TEST_MODE__
+               #ifdef __MMFILE_TEST_MODE__
                        debug_msg(RELEASE, "find Video Stream+++++++[%2d]", idx++);
-                       #endif
+               #endif
 
                        /* Decode video frame*/
                        len = avcodec_send_packet(pVideoCodecCtx, &packet);
@@ -473,76 +463,142 @@ static int __mmfile_get_frame(AVFormatContext *pFormatCtx, int64_t timestamp, bo
        /*free pkt after loop breaking*/
        av_packet_unref(&packet);
 
-       /* Did we get a video frame?*/
-       if (find) {
+       return find;
+}
 
-               debug_msg(RELEASE, "Find Frame");
+static int __mmfile_swscale_frame(AVCodecContext *pVideoCodecCtx, AVFrame *pFrame, int width, int height, unsigned char *frame, int size)
+{
+       int ret = MMFILE_FORMAT_SUCCESS;
+       int av_err = 0;
+       uint8_t *dst_data[4];
+       int dst_linesize[4];
+       struct SwsContext *img_convert_ctx = NULL;
+
+       av_err = av_image_fill_arrays(dst_data, dst_linesize, frame, AV_PIX_FMT_RGB24, width, height, 1);
+       if (av_err < 0) {
+               debug_error(DEBUG, "error: avpicture_fill fail. errcode = 0x%08X\n", ret);
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception;
+       }
 
-               /* return frame infromations*/
-               if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
-                       *width = pVideoCodecCtx->coded_width;
-                       *height = pVideoCodecCtx->coded_height;
-               } else {
-                       *width = pVideoCodecCtx->width;
-                       *height = pVideoCodecCtx->height;
-               }
+       img_convert_ctx = sws_getContext(width, height, pVideoCodecCtx->pix_fmt, width, height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
 
-               *size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, *width, *height, 1);
+       if (!img_convert_ctx) {
+               debug_error(DEBUG, "failed to get img convet ctx\n");
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception;
+       }
 
-               if (*size > 0)
-                       *frame = mmfile_malloc(*size);
+       av_err = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize, 0, height, dst_data, dst_linesize);
+       if (av_err < 0) {
+               debug_error(DEBUG, "failed to convet image\n");
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception;
+       }
+exception:
+       sws_freeContext(img_convert_ctx);
+       img_convert_ctx = NULL;
 
-               if (NULL == *frame) {
-                       debug_error(DEBUG, "error: avpicture_get_size. [%d]\n", *size);
-                       ret = MMFILE_FORMAT_FAIL;
-                       goto exception;
-               }
+       return ret;
+}
 
-               debug_msg(RELEASE, "size : %d", *size);
-               debug_msg(RELEASE, "width : %d", *width);
-               debug_msg(RELEASE, "height : %d", *height);
-               debug_msg(RELEASE, "frame : %p", *frame);
-
-               uint8_t *dst_data[4];
-               int dst_linesize[4];
-               ret = av_image_fill_arrays(dst_data, dst_linesize, *frame, AV_PIX_FMT_RGB24, *width, *height, 1);
-               if (ret < 0) {
-                       debug_error(DEBUG, "error: avpicture_fill fail. errcode = 0x%08X\n", ret);
-                       ret = MMFILE_FORMAT_FAIL;
-                       goto exception;
-               }
+static int __mmfile_get_frame(AVFormatContext *pFormatCtx, int64_t timestamp, bool is_accurate, unsigned char **frame, int *size, int *width, int *height)
+{
+       int ret = MMFILE_FORMAT_SUCCESS;
+       int videoStream = -1;
+       AVCodecContext *pVideoCodecCtx = NULL;
+       bool find = false;
+       AVFrame *pFrame = NULL;
+
+       /* Retrieve stream information */
+       if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
+               debug_error(DEBUG, "error : av_find_stream_info failed");
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception; /* Couldn't find stream information */
+       }
+
+       /* Find the first video stream */
+       ret = __mmfile_get_first_video_stream(pFormatCtx, &videoStream);
+       if (MMFILE_FORMAT_FAIL == ret) {
+               debug_error(DEBUG, "error : __mmfile_get_first_video_stream");
+               goto exception; /* Didn't find a video stream */
+       }
 
-               struct SwsContext *img_convert_ctx = NULL;
+       ret = __mmfile_open_video_codec(pFormatCtx, videoStream, &pVideoCodecCtx);
+       if (MMFILE_FORMAT_FAIL == ret) {
+               debug_error(DEBUG, "error : __mmfile_open_video_codec");
+               goto exception; /*Could not open codec */
+       }
 
-               img_convert_ctx = sws_getContext(*width, *height, pVideoCodecCtx->pix_fmt, *width, *height, AV_PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);
+       /* Storing Data  */
+       /* Allocate video frame */
+       pFrame = av_frame_alloc();
+       if (!pFrame) {
+               debug_error(DEBUG, "error: pFrame is NULL\n");
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception;
+       }
 
-               if (NULL == img_convert_ctx) {
-                       debug_error(DEBUG, "failed to get img convet ctx\n");
-                       ret = MMFILE_FORMAT_FAIL;
-                       goto exception;
-               }
+       /* Seeking */
+       ret = __mmfile_seek_to_pos(pFormatCtx, timestamp, is_accurate);
+       if (MMFILE_FORMAT_FAIL == ret) {
+               debug_error(DEBUG, "error : __mmfile_seek_to_pos");
+               goto exception; /*Could not seek to timestamp */
+       }
 
-               ret = sws_scale(img_convert_ctx, (const uint8_t * const *)pFrame->data, pFrame->linesize, 0, *height, dst_data, dst_linesize);
-               if (ret < 0) {
-                       debug_error(DEBUG, "failed to convet image\n");
-                       sws_freeContext(img_convert_ctx);
-                       img_convert_ctx = NULL;
-                       ret = MMFILE_FORMAT_FAIL;
-                       goto exception;
-               }
+       /* Reading Data */
+       find = __mmfile_find_proper_frame(pFormatCtx, videoStream, pVideoCodecCtx, timestamp, is_accurate, pFrame);
 
-               sws_freeContext(img_convert_ctx);
-               img_convert_ctx = NULL;
+       /* Did we get a video frame?*/
+       if (!find) {
+               debug_error(DEBUG, "Not Found Proper Frame[%d]", find);
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception;
+       }
 
-#ifdef MMFILE_FORMAT_DEBUG_DUMP
-               __save_frame(dst_data, dst_linesize, pVideoCodecCtx->width, pVideoCodecCtx->height, (int)(pos / 1000));
-#endif
+       debug_msg(RELEASE, "Find Frame");
+
+       /* return frame infromations*/
+       if ((pVideoCodecCtx->width == 0) || (pVideoCodecCtx->height == 0)) {
+               *width = pVideoCodecCtx->coded_width;
+               *height = pVideoCodecCtx->coded_height;
        } else {
-               debug_error(DEBUG, "Not Found Proper Frame[%d]", find);
+               *width = pVideoCodecCtx->width;
+               *height = pVideoCodecCtx->height;
+       }
+
+       *size = av_image_get_buffer_size(AV_PIX_FMT_RGB24, *width, *height, 1);
+
+       if (*size <=0 ) {
+               debug_error(DEBUG, "error: av_image_get_buffer_size. [%d]\n", *size);
                ret = MMFILE_FORMAT_FAIL;
                goto exception;
        }
 
+       *frame = mmfile_malloc(*size);
+       if (!(*frame)) {
+               debug_error(DEBUG, "error: avpicture_get_size. [%d]\n", *size);
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception;
+       }
+
+       debug_msg(RELEASE, "size : %d", *size);
+       debug_msg(RELEASE, "width : %d", *width);
+       debug_msg(RELEASE, "height : %d", *height);
+       debug_msg(RELEASE, "frame : %p", *frame);
+
+       ret = __mmfile_swscale_frame(pVideoCodecCtx, pFrame, *width, *height, *frame, *size);
+       if (MMFILE_FORMAT_FAIL == ret) {
+               debug_error(DEBUG, "error : __mmfile_scale_frame");
+               ret = MMFILE_FORMAT_FAIL;
+               goto exception;
+       }
+
+#ifdef MMFILE_FORMAT_DEBUG_DUMP
+       __save_frame(*width, *height, *frame, *size, (int)(timestamp / 1000));
+#endif
+       debug_msg(RELEASE, "frame : %p", *frame);
+
        if (pFrame)                     av_frame_free(&pFrame);
        if (pVideoCodecCtx)     avcodec_free_context(&pVideoCodecCtx);