#define _GNU_SOURCE
#include <stdio.h>
#include <pthread.h>
#include <sched.h>
#include "libavcodec/avcodec.h"
#include <stdint.h>
#include "libavutil/avutil.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"//#include "faac.h"
#include "mp4_muxer.h"
#include <arpa/inet.h>
#include "libavformat/avformat.h"
#include <time.h>
#define USE_H264BSF 0
#define USE_AACBSF 0
// 要保存的MP4文件路径
static char* mFileName[MEDIA_CHAN_CNT] = {NULL};
// 输入AAC音频上下文
static AVFormatContext* mInputAudioContext[MEDIA_CHAN_CNT] = {NULL};
// 输入H264视频上下文
static AVFormatContext* mInputVideoContext[MEDIA_CHAN_CNT] = {NULL};
// 输出媒体格式上下文
static AVFormatContext* mOutputFrmtContext[MEDIA_CHAN_CNT] = {NULL};
// AAC音频位流筛选上下文
static AVBitStreamFilterContext* mAudioFilter[MEDIA_CHAN_CNT] = {NULL};
// H264视频位流筛选上下文
static AVBitStreamFilterContext* mVideoFilter[MEDIA_CHAN_CNT] = {NULL};
// AAC数据缓存区
static unsigned char* mAudioBuffer[MEDIA_CHAN_CNT] = {NULL};
// AAC数据读写队列
static CESimpleQueue* mAudioQueue[MEDIA_CHAN_CNT] = {NULL};
// H264数据缓冲区
static unsigned char* mVideoBuffer[MEDIA_CHAN_CNT] = {NULL};
// H264数据读写队列
static CESimpleQueue* mVideoQueue[MEDIA_CHAN_CNT] = {NULL};
// 音频在mInputAudioContext->streams流中的索引
static int mAudioIndex[MEDIA_CHAN_CNT] = {-1,-1};
// 视频在mInputVideoContext->streams流中的索引
static int mVideoIndex[MEDIA_CHAN_CNT] = {-1,-1};;
// 输出流中音频帧的索引
static int mAudioOutIndex[MEDIA_CHAN_CNT] = {-1,-1};;
// 输出流视频帧的索引
static int mVideoOutIndex[MEDIA_CHAN_CNT] = {-1,-1};
static pthread_t gs_MuxerPid[MEDIA_CHAN_CNT];
static volatile MUXER_PROC_PARA_t gs_MuxerPara[MEDIA_CHAN_CNT];
static volatile int video_frame_index[MEDIA_CHAN_CNT] = {0};
static volatile int audio_frame_index[MEDIA_CHAN_CNT] = {0};
static volatile int mp4File_open[MEDIA_CHAN_CNT] = {0};
//static pthread_mutex_t videoQueueMutex;
//static pthread_mutex_t audioQueueMutex;
static pthread_mutex_t proc_mutex;
static MUXER_PROC proc_array[MEDIA_CHAN_CNT];
#if 0
static CESimpleQueue gs_videoQueue;
static CEQueueItem gs_videoQueueItem[VIDEO_QUEUE_SIZE];
static unsigned char videoBuf[VIDEO_QUEUE_SIZE][VIDEO_ITEM_SIZE];
static CESimpleQueue gs_audioQueue;
static CEQueueItem gs_audioQueueItem[VIDEO_QUEUE_SIZE];
static unsigned char audioBuf[VIDEO_QUEUE_SIZE][VIDEO_ITEM_SIZE];
#endif
/** Comments: 创建一个指定大小的队列
* Param aCount: 队列项的个数
* Param aItemSize: 队列每项的字节数
* @Return 创建的队列, 失败返回NULL
*/
static CESimpleQueue* CreateQueue(int aCount, int aItemSize)
{
int i;
#if 1
CESimpleQueue* queue = (CESimpleQueue *)malloc(sizeof(CESimpleQueue));
if (queue == NULL)
{
return NULL;
}
queue->Items = (CEQueueItem *)malloc(sizeof(CEQueueItem) * aCount);
if (queue->Items == NULL)
{
// 释放申请的内存
free(queue);
return NULL;
}
for (i = 0; i < aCount; i++)
{
queue->Items[i].Bytes = (uint8_t *)malloc(aItemSize);
queue->Items[i].TotalSize = aItemSize;
queue->Items[i].EnqueueSize = 0;
queue->Items[i].DequeueSize = 0;
}
queue->Count = aCount;
queue->DequeueIndex = 0;
queue->EnqueueIndex = 0;
pthread_mutex_init(&queue->mutex,NULL);
return queue;
#endif
#if 0
gs_videoQueue.Items = &gs_videoQueueItem[0];
for (i = 0; i < aCount; i++)
{
gs_videoQueue.Items[i].Bytes = &videoBuf[i][0];
gs_videoQueue.Items[i].TotalSize = aItemSize;
gs_videoQueue.Items[i].EnqueueSize = 0;
gs_videoQueue.Items[i].DequeueSize = 0;
}
gs_videoQueue.Count = aCount;
gs_videoQueue.DequeueIndex = 0;
gs_videoQueue.EnqueueIndex = 0;
pthread_mutex_init(&gs_videoQueue.mutex,NULL);
return &gs_videoQueue;
#endif
}
/** Comments: 销毁队列
* Param aQueue: 要销毁的队列
* @Return void
*/
static void DestroyQueue(CESimpleQueue* aQueue)
{
int i;
if (aQueue == NULL)
{
return;
}
pthread_mutex_destroy(&aQueue->mutex);
// 释放队列所有申请的内存
for (i = 0; i < aQueue->Count; i++)
{
free(aQueue->Items[i].Bytes);
}
free(aQueue->Items);
free(aQueue);
}
/** Comments: 队列数据入队操作
* Param aQueue: 队列实体, 函数内部不进行空检测
* Param aBytes: 要入队的数据
* Param aSize: 要入队的数据字节数
* @Return 入队成功与否
*/
static int AudioEnqueue(CESimpleQueue* aQueue, char* aBytes, int aSize)
{
if (!aQueue || aBytes == NULL || aSize < 0)
{
printf("AudioEnqueue aQueue:%d aBytes %d aSize:%d\n",aQueue,aBytes,aSize);
return -3;
}
pthread_mutex_lock(&aQueue->mutex);
int tail = aQueue->EnqueueIndex;
int size = FFMIN(aSize, aQueue->Items[tail].TotalSize);
while (size > 0)
{
//printf("tail:%d size:%d\n",tail,size);
memcpy(aQueue->Items[tail].Bytes, aBytes, size);
aQueue->Items[tail].EnqueueSize = size;
aQueue->Items[tail].DequeueSize = 0;
aQueue->EnqueueIndex = (aQueue->EnqueueIndex + 1) % aQueue->Count;
tail = aQueue->EnqueueIndex;
// 数据过多, 继续入队
aSize -= size;
aBytes += size;
size = FFMIN(aSize, aQueue->Items[tail].TotalSize);
}
pthread_mutex_unlock(&aQueue->mutex);
return 0;
}
static int VideoEnqueue(CESimpleQueue* aQueue, char* aBytes, int aSize)
{
static unsigned long long sumvideoItem = 0;
if (!aQueue || aBytes == NULL || aSize < 0)
{
printf("VideoEnqueue aQueue:%d aBytes %d aSize:%d\n",aQueue,aBytes,aSize);
return -3;
}
pthread_mutex_lock(&aQueue->mutex);
int tail = aQueue->EnqueueIndex;
int size = FFMIN(aSize, aQueue->Items[tail].TotalSize);
while (size > 0)
{
sumvideoItem++;
//printf("VideoEnqueue tail:%d size:%d sumvideoItem:%d\n",tail,size,sumvideoItem);
if(((aQueue->EnqueueIndex + 1) % aQueue->Count) == aQueue->DequeueIndex)
{
printf("VideoEnqueue full error!\n");
usleep(33333);
}
memcpy(aQueue->Items[tail].Bytes, aBytes, size);
aQueue->Items[tail].EnqueueSize = size;
aQueue->Items[tail].DequeueSize = 0;
aQueue->EnqueueIndex = (aQueue->EnqueueIndex + 1) % aQueue->Count;
tail = aQueue->EnqueueIndex;
// 数据过多, 继续入队
aSize -= size;
aBytes += size;
size = FFMIN(aSize, aQueue->Items[tail].TotalSize);
}
pthread_mutex_unlock(&aQueue->mutex);
return 0;
}
static int GetEnqueueDataItem(CESimpleQueue* aQueue)
{
int dataItem = 0;
if (!aQueue)
{
return -1;
}
pthread_mutex_lock(&aQueue->mutex);
if(aQueue->EnqueueIndex >= aQueue->DequeueIndex)
{
dataItem = aQueue->EnqueueIndex - aQueue->DequeueIndex;
}
else
{
dataItem = aQueue->EnqueueIndex + (aQueue->Count-aQueue->DequeueIndex);
}
pthread_mutex_unlock(&aQueue->mutex);
return dataItem;
}
static int VideoGetEnqueueDataItem(int chan)
{
int ret = 0;
//pthread_mutex_lock(&videoQueueMutex);
ret = GetEnqueueDataItem(mVideoQueue[chan]);
//pthread_mutex_unlock(&videoQueueMutex);
return ret;
}
static int AudioGetEnqueueDataItem(int chan)
{
int ret = 0;
//pthread_mutex_lock(&audioQueueMutex);
ret = GetEnqueueDataItem(mAudioQueue[chan]);
//pthread_mutex_unlock(&audioQueueMutex);
return ret;
}
/** Comments: 读取媒体内存流数据的FFMPEG回调方法 出队操作
* Param aHandle: 队列句柄* Param aBytes: [输出] 要读取的数据
* Param aSize: 要读取的字节数
* @Return 读取到的实际字节个数
*/
static int VideoReadBytesCallback(void *opaque, uint8_t *buf, int buf_size)
{
static unsigned long long readSumvideoItem = 0;
//pthread_mutex_lock(&videoQueueMutex);
CESimpleQueue *pQueue = (CESimpleQueue *)opaque;
//pthread_mutex_lock(&videoQueueMutex);
pthread_mutex_lock(&pQueue->mutex);
// printf("[%d] %s buf_size:%d\n",__LINE__, __FUNCTION__,buf_size);
if (pQueue->DequeueIndex == pQueue->EnqueueIndex)
{
//printf("VideoReadBytes failed! DequeueIndex:%d >>>>>>>>>>>>>>>>>>\n",pQueue->DequeueIndex);
//pthread_mutex_unlock(&videoQueueMutex);
pthread_mutex_unlock(&pQueue->mutex);
- 1
- 2
前往页