123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- // SPDX-License-Identifier: LGPL-2.1 OR BSD-3-Clause
- /*
- * Copyright (c) 2018, Chips&Media
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <time.h>
- #include "main_helper.h"
- #include "libavformat/avformat.h"
- static BOOL initFFmpeg;
- typedef struct FeederFrameContext {
- AVFormatContext* avContext;
- BOOL isFirstPacket;
- Uint32 videoIndex;
- Uint8* tempBuffer;
- Uint32 tempRdPtr;
- Uint32 tempWrPtr;
- } FeederFrameContext;
- void* BSFeederFrameSize_Create(const char* path)
- {
- /*lint -esym(438, avContext) */
- FeederFrameContext* ffmpegReader = NULL;
- AVFormatContext* avContext = NULL;
- AVCodecContext* codec = NULL;
- AVInputFormat* fmt = NULL;
- Int32 error;
- Int32 videoIndex;
- jdi_lock();
- if (initFFmpeg == FALSE) {
- av_register_all();
- initFFmpeg = TRUE;
- }
- jdi_unlock();
- if ((avContext=avformat_alloc_context()) == NULL) {
- return NULL;
- }
- avContext->flags |= CODEC_FLAG_TRUNCATED;
- if ((error=avformat_open_input(&avContext, path, fmt, NULL))) {
- JLOG(ERR, "%s:%d failed to av_open_input_file error(%d), %s\n",
- __FILE__, __LINE__, error, path);
- goto __failed_to_end;
- }
- if ((error=avformat_find_stream_info(avContext, NULL)) < 0) {
- JLOG(ERR, "%s:%d failed to avformat_find_stream_info. error(%d)\n",
- __FUNCTION__, __LINE__, error);
- goto __failed_to_end;
- }
- videoIndex = av_find_best_stream(avContext, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);
- if (videoIndex < 0) {
- JLOG(ERR, "%s:%d failed to av_find_best_stream.\n", __FUNCTION__, __LINE__);
- goto __failed_to_end;
- }
- codec = avContext->streams[videoIndex]->codec;
- if (codec->codec_id != AV_CODEC_ID_MJPEG) {
- JLOG(ERR, "%s:%d Not supported codec_id: %d\n", __FUNCTION__, __LINE__, codec->codec_id);
- goto __failed_to_end;
- }
- if ((ffmpegReader=(FeederFrameContext*)malloc(sizeof(FeederFrameContext))) == NULL)
- goto __failed_to_end;
- ffmpegReader->avContext = avContext;
- ffmpegReader->videoIndex = videoIndex;
- ffmpegReader->isFirstPacket = TRUE;
- ffmpegReader->tempBuffer = NULL;
- ffmpegReader->tempRdPtr = 0;
- ffmpegReader->tempWrPtr = 0;
- return (void*)ffmpegReader;
- __failed_to_end:
- if (avContext) {
- avformat_free_context(avContext);
- avContext = NULL;
- }
- if (ffmpegReader) {
- free(ffmpegReader);
- }
- return NULL;
- /*lint +esym(438, avContext) */
- }
- BOOL BSFeederFrameSize_Destroy(
- void* feeder
- )
- {
- FeederFrameContext* ctx = (FeederFrameContext*)feeder;
- if (ctx == NULL) {
- JLOG(ERR, "%s:%d Invalid handle\n", __FUNCTION__, __LINE__);
- return FALSE;
- }
- if (ctx->avContext)
- avformat_close_input(&ctx->avContext);
- free(ctx);
- return TRUE;
- }
- Int32 BSFeederFrameSize_Act(void* feeder, BSChunk* packet)
- {
- FeederFrameContext* ffmpegReader = (FeederFrameContext*)feeder;
- AVFormatContext* avFormatContext = ffmpegReader->avContext;
- AVPacket avpacket;
- Int32 error;
- Uint8* ptr;
- Uint32 size;
- Int32 packetSize = -1;
- if (ffmpegReader->tempBuffer) {
- goto __consume_tempBuffer;
- }
- av_init_packet(&avpacket);
- while (TRUE) {
- error = av_read_frame(avFormatContext, &avpacket);
- if (error < 0) {
- if (error == AVERROR_EOF || avFormatContext->pb->eof_reached == TRUE) {
- packet->eos = TRUE;
- return 0;
- }
- else {
- JLOG(ERR, "%s:%d failed to av_read_frame error(0x%08x)\n",
- __FUNCTION__, __LINE__, error);
- goto __end_read;
- }
- }
- if (avpacket.stream_index != ffmpegReader->videoIndex)
- continue;
- break;
- }
- if (avpacket.size == 0)
- return 0;
- if (avpacket.size >= (signed)packet->size )
- {
- JLOG(ERR, "one packet size(%d) is bigger than STREAM_BUF_SIZE(%d)\n", avpacket.size, packet->size);
- return -1;
- }
-
- memset(packet->data, 0x00, packet->size);
- ptr = avpacket.data;
- size = avpacket.size;
- memcpy((char*)packet->data, ptr, size);
- packetSize = size;
- if (avFormatContext->pb->eof_reached && avFormatContext->packet_buffer == NULL) {
- packet->eos = TRUE;
- }
- __end_read:
- av_free_packet(&avpacket);
- return packetSize;
- __consume_tempBuffer:
- if (ffmpegReader->tempBuffer != NULL) {
- memcpy(packet->data, ffmpegReader->tempBuffer, ffmpegReader->tempWrPtr);
- packetSize = ffmpegReader->tempWrPtr;
- free(ffmpegReader->tempBuffer);
- ffmpegReader->tempBuffer = NULL;
- ffmpegReader->tempWrPtr = 0;
- ffmpegReader->tempRdPtr = 0;
- }
- return packetSize;
- }
- BOOL BSFeederFrameSize_Rewind(
- void* feeder
- )
- {
- FeederFrameContext* ffmpegReader = (FeederFrameContext*)feeder;
- AVFormatContext* avFormatContext = ffmpegReader->avContext;
- Int32 ret;
- if ((ret=av_seek_frame(avFormatContext, ffmpegReader->videoIndex, 0, 0)) < 0) {
- JLOG(ERR, "%s:%d Failed to av_seek_frame:(ret:%d)\n", __FUNCTION__, __LINE__, ret);
- return FALSE;
- }
- return TRUE;
- }
|