#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,};
/* 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);
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*/
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) {
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)
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);
/*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);