static int decode_interrupt_cb(void *ctx) {
THREAD_ARGS_S *pThreadArgs = (THREAD_ARGS_S*)ctx;
int src = pThreadArgs->src;
return g_bSaveStream[src] == HI_TRUE?0:1;
}
static AVStream *add_stream(AVFormatContext *ofmt_ctx, AVCodecParameters *in_codecpar, int pid)
{
int Ret;
AVStream * out_stream = avformat_new_stream(ofmt_ctx, NULL);
if (!out_stream) {
printf("Failed allocating output stream\n");
return NULL;
}
Ret = avcodec_parameters_copy(out_stream->codecpar, in_codecpar);
if (Ret < 0) {
printf("Failed to copy codec parameters\n");
return NULL;
}
out_stream->id = pid;
out_stream->codecpar->codec_tag = 0;
return out_stream;
}
//int gtestfd;
//output ts pkt
int ts_out_callback(void *opaque, uint8_t *buf, int buf_size)
{
//printf("%s IN buf_size %d --line-- %d\n",__FUNCTION__, buf_size,__LINE__);
THREAD_ARGS_S *pThreadArgs = (THREAD_ARGS_S*)opaque;
int index ;
index= pThreadArgs->src;
//write(gtestfd, buf, buf_size);
buf_size = CamTSMuxer_WriteData(index, buf, buf_size);
//printf("%s --line-- OUT %d \n",__FUNCTION__,__LINE__);
return buf_size;
}
int get_h264_buffer(void *opaque, uint8_t *buf, int buf_size)
{
THREAD_ARGS_S *pThreadArgs = (THREAD_ARGS_S*)opaque;
int src = pThreadArgs->src;
int Ret;
HI_BOOL bGotStream;
HI_UNF_VENC_STREAM_S stVencStream;
//printf("%s --line-- src %d buf_size %d IN %d \n",__FUNCTION__, src,buf_size,__LINE__);
/*save video stream*/
while (g_bSaveStream[src] == HI_TRUE)
{
pthread_mutex_lock(&g_VencMutex[src]);
Ret = HI_UNF_VENC_AcquireStream(hVenc[src],&stVencStream,0);
if ((HI_SUCCESS == Ret) && (stVencStream.u32SlcLen > 0))
{
buf_size = FFMIN(buf_size, stVencStream.u32SlcLen);
if (stVencStream.u32SlcLen > buf_size)
printf("%s --line-- buf_size %d u32SlcLen %d %d \n",__FUNCTION__, buf_size,stVencStream.u32SlcLen, __LINE__);
memcpy(buf, stVencStream.pu8Addr, buf_size);
//printf("video pts write index %d\n", g_vpts_w_index[src]);
//g_video_pts_queue[src][g_vpts_w_index[src]] = stVencStream.u32PtsMs;
g_video_pts_queue[src][0] = stVencStream.u32PtsMs;
if (g_vpts_w_index[src]+1 >= MAX_PTS_QUEUE_SIZE)
g_vpts_w_index[src] = 0;
else
g_vpts_w_index[src] ++;
Ret = HI_UNF_VENC_ReleaseStream(hVenc[src],&stVencStream);
if (HI_SUCCESS != Ret)
{
printf("[%s] HI_UNF_VENC_ReleaseStream failed 0x%x\n", __FUNCTION__, Ret);
pthread_mutex_unlock(&g_VencMutex[src]);
return -1;
}
vencsize[src] += stVencStream.u32SlcLen;
pthread_mutex_unlock(&g_VencMutex[src]);
bGotStream = HI_TRUE;
return buf_size;//success
}
else if ( HI_ERR_VENC_BUF_EMPTY != Ret)
{
printf("HI_UNF_VENC_AcquireStream failed:%#x\n",Ret);
pthread_mutex_unlock(&g_VencMutex[src]);
return -1;
}
pthread_mutex_unlock(&g_VencMutex[src]);
usleep(2000);
}
//printf("%s --line-- OUT %d \n",__FUNCTION__, __LINE__);
return -1;
}
int get_aac_buffer(void *opaque, uint8_t *buf, int buf_size)
{
//printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
THREAD_ARGS_S *pThreadArgs = (THREAD_ARGS_S*)opaque;
int src = pThreadArgs->src;
HI_BOOL bGotStream;
int Ret;
//HI_UNF_VENC_STREAM_S stTencStream;
HI_UNF_ES_BUF_S stAencStream;
while (g_bSaveStream[src] == HI_TRUE)
{
/*save audio stream*/
if(g_bAudioTranscoding[src] == HI_TRUE)
{
Ret = HI_UNF_AENC_AcquireStream(hAenc[src],&stAencStream,0);
if ((HI_SUCCESS == Ret) && (stAencStream.u32BufLen > 0))
{
buf_size = FFMIN(buf_size, stAencStream.u32BufLen);
memcpy(buf, stAencStream.pu8Buf, buf_size);
//printf("audio pts write index %d\n", g_apts_w_index[src]);
g_audio_pts_queue[src][g_apts_w_index[src]] = stAencStream.u32PtsMs;
//g_audio_pts_queue[src][0] = stAencStream.u32PtsMs;
if (g_apts_w_index[src]+1 >= MAX_PTS_QUEUE_SIZE)
g_apts_w_index[src] = 0;
else
g_apts_w_index[src] ++;
Ret = HI_UNF_AENC_ReleaseStream(hAenc[src],&stAencStream);
if (HI_SUCCESS != Ret)
{
printf("[%s] HI_UNF_AENC_ReleaseStream failed 0x%x\n", __FUNCTION__, Ret);
return -1;
}
aencsize[src] += stAencStream.u32BufLen;
bGotStream = HI_TRUE;
return buf_size;
}
else if ( HI_ERR_AENC_OUT_BUF_EMPTY != Ret)
{
printf("HI_UNF_AENC_AcquireStream failed:%#x\n",Ret);
return -1;
}
}
usleep(2000);
}
return -1;
}
HI_VOID SaveAudioThread(HI_VOID *args)
{
THREAD_ARGS_S *pThreadArgs = (THREAD_ARGS_S*)args;
//HI_HANDLE XCodeHandle = pThreadArgs->XCodeHandle;
int src = pThreadArgs->src;
AVPacket pkt = { 0 }; // data and size must be 0;
av_init_packet(&pkt);
int Ret;
int drop_audio = 100;
printf("SaveAudioThread enter ...........................for src=(%d)\n",src);
while (g_bSaveStream[src] == HI_TRUE)
{
Ret = av_read_frame(g_ifmt_ctx_a[src], &pkt);
if (Ret < 0)
break;
pthread_mutex_lock(&g_wirteframelock);
if (drop_audio > 0)
{
pkt.stream_index = 1;
//printf("audio pts read index %d\n", g_apts_r_index[src]);
pkt.pts = (g_audio_pts_queue[src][g_apts_r_index[src]]) * 90;
//pkt.pts = (g_audio_pts_queue[src][0]) * 90;
pkt.dts = (GetSysTimeMs() -g_Muxing_time[src])*90 + 20000*90;//pkt.pts;
if (g_apts_r_index[src]+1 >= MAX_PTS_QUEUE_SIZE)
g_apts_r_index[src] = 0;
else
g_apts_r_index[src] ++;
Ret = av_interleaved_write_frame(g_ofmt_ctx[src], &pkt);
if (Ret < 0) {
printf("Error muxing audio packet\n");
}
}
else
drop_audio--;
pthread_mutex_unlock(&g_wirteframelock);
av_packet_unref(&pkt);
}
}
HI_VOID SaveThread(HI_VOID *args)
{
THREAD_ARGS_S *pThreadArgs = (THREAD_ARGS_S*)args;
HI_HANDLE XCodeHandle;
int src;
HI_S32 Ret;
XCodeHandle = pThreadArgs->XCodeHandle;
src = pThreadArgs->src;
//gtestfd = open("/tmp/test2.ts", O_CREAT|O_RDWR|O_TRUNC, 0666);
AVOutputFormat *fmt = NULL;
AVFormatContext *ofmt_ctx;
AVFormatContext *ifmt_ctx_v = NULL, *ifmt_ctx_a = NULL;
g_Muxing_time[src] = GetSysTimeMs();
g_vpts_r_index[src] = 0;
g_vpts_w_index[src] = 0;
g_apts_r_index[src] = 0;
g_apts_w_index[src] = 0;
AVPacket pkt = { 0 }; // data and size must be 0;
av_init_packet(&pkt);
printf("SaveThread enter ...........................for src=(%d)\n",src);
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
/* allocate the input video context */
unsigned char* inbuffer_v = NULL;
inbuffer_v = (unsigned char*)av_malloc(1024*1024*2);
AVIOContext *avio_in_v = avio_alloc_context(inbuffer_v, 1024*1024*2, 0, args, get_h264_buffer, NULL,NULL);
avio_in_v->max_packet_size = 128*1024;
ifmt_ctx_v = avformat_alloc_context();
ifmt_ctx_v->interrupt_callback.callback = decode_interrupt_cb;
ifmt_ctx_v->interrupt_callback.opaque = args;
ifmt_ctx_v->probesize = 1024*512;
ifmt_ctx_v->max_analyze_duration = 2 * AV_TIME_BASE;
ifmt_ctx_v->pb = avio_in_v;
AVInputFormat *file_iformat_v = av_find_input_format("h264");
if ((Ret = avformat_open_input(&ifmt_ctx_v, "", file_iformat_v, 0)) < 0) {
printf( "Could not open input file.\n");
return ;
}
if ((Ret = avformat_find_stream_info(ifmt_ctx_v, 0)) < 0) {
printf( "Failed to retrieve input stream information\n");
return ;
}
av_dump_format(ifmt_ctx_v, 0, "video", 0);
/* allocate the input audio context */
unsigned char* inbuffer_a = NULL;
inbuffer_a = (unsigned char*)av_malloc(1024*128);
AVIOContext *avio_in_a = avio_alloc_context(inbuffer_a, 1024*128, 0, args, get_aac_buffer, NULL,NULL);
avio_in_a->max_packet_size = 64*1024;
ifmt_ctx_a = avformat_alloc_context();
ifmt_ctx_a->interrupt_callback.callback = decode_interrupt_cb;
ifmt_ctx_a->interrupt_callback.opaque = args;
ifmt_ctx_a->probesize = 1024*32;
ifmt_ctx_a->max_analyze_duration = 2 * AV_TIME_BASE;
ifmt_ctx_a->pb = avio_in_a;
AVInputFormat *file_iformat_a = av_find_input_format("aac");
if ((Ret = avformat_open_input(&ifmt_ctx_a, "", file_iformat_a, 0)) < 0) {
printf( "Could not open input file.\n");
return ;
}
if ((Ret = avformat_find_stream_info(ifmt_ctx_a, 0)) < 0) {
printf( "Failed to retrieve input stream information\n");
return ;
}
av_dump_format(ifmt_ctx_a, 0, "audio", 0);
unsigned char* outbuffer = NULL;
outbuffer = (unsigned char*)av_malloc(1024*64);
AVIOContext *avio_out = avio_alloc_context(outbuffer, 1024*64, 1, args, NULL, ts_out_callback,NULL);
/* allocate the output media context */
avformat_alloc_output_context2(&ofmt_ctx, NULL, "mpegts", NULL);
if (!ofmt_ctx) {
printf("Could not create output context\n");
Ret = AVERROR_UNKNOWN;
return ;
}
ofmt_ctx->pb = avio_out;
ofmt_ctx->interrupt_callback.callback = decode_interrupt_cb;
ofmt_ctx->interrupt_callback.opaque = args;
ofmt_ctx->flags =AVFMT_FLAG_CUSTOM_IO;
ofmt_ctx->flags |= AVFMT_FLAG_FLUSH_PACKETS;
fmt = ofmt_ctx->oformat;
fmt->flags |= AVFMT_NOFILE;
fmt->flags |= AVFMT_TS_NONSTRICT;
/* Add the audio and video streams using the default format codecs
* and initialize the codecs. */
CTSMUX_DESCR_PRG_STREAM * pStr= NULL;
pTsDescr[src]->curPrg = pTsDescr[src]->pPrg[0];
#if 1
AVStream *in_stream_v = ifmt_ctx_v->streams[0];
AVCodecParameters *in_codecpar_v = in_stream_v->codecpar;
pStr = &(pTsDescr[src]->curPrg->stream[0]);
add_stream(ofmt_ctx, in_codecpar_v, pStr->pid);
#endif
#if 1
AVStream *in_stream_a = ifmt_ctx_a->streams[0];
AVCodecParameters *in_codecpar_a = in_stream_a->codecpar;
pStr = &(pTsDescr[src]->curPrg->stream[1]);
add_stream(ofmt_ctx, in_codecpar_a, pStr->pid);
#endif
//av_dump_format(ofmt_ctx, 0, "out_ts", 0);
AVDictionary *opt = NULL;
av_dict_set_int(&opt, "mpegts_pmt_start_pid", pTsDescr[src]->curPrg->pmt.pid, 0);
/* Write the stream header, if any. */
Ret = avformat_write_header(ofmt_ctx, &opt);
if (Ret < 0) {
fprintf(stderr, "Error occurred when opening output file: %s\n",
av_err2str(Ret));
return ;
}
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
g_ifmt_ctx_a[src] = ifmt_ctx_a;
g_ofmt_ctx[src] = ofmt_ctx;
pthread_t audio_Thd;
pthread_create(&audio_Thd, HI_NULL, (HI_VOID *)SaveAudioThread, args);
#if 1
while (g_bSaveStream[src] == HI_TRUE)
{
#if 1
{
Ret = av_read_frame(ifmt_ctx_v, &pkt);
if (Ret < 0)
break;
pthread_mutex_lock(&g_wirteframelock);
//av_packet_rescale_ts(&pkt, in_stream->time_base, out_stream->time_base);
//pkt.pos = -1;
//printf("video pts read index %d\n", g_vpts_r_index[src]);
//pkt.pts = (g_video_pts_queue[src][g_vpts_r_index[src]]) * 90;
pkt.pts = (g_video_pts_queue[src][0]) * 90;
pkt.dts = pkt.pts;
if (g_vpts_r_index[src]+1 >= MAX_PTS_QUEUE_SIZE)
g_vpts_r_index[src] = 0;
else
g_vpts_r_index[src] ++;
Ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
if (Ret < 0) {
printf("Error muxing video packet\n");
}
pthread_mutex_unlock(&g_wirteframelock);
av_packet_unref(&pkt);
}
#endif
#if 0
{
Ret = av_read_frame(g_ifmt_ctx_a[src], &pkt);
if (Ret < 0)
break;
//pthread_mutex_lock(&g_wirteframelock);
pkt.stream_index = 1;
Ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
if (Ret < 0) {
printf("Error muxing audio packet\n");
}
//pthread_mutex_unlock(&g_wirteframelock);
av_packet_unref(&pkt);
}
#endif
}
#endif
pthread_join(audio_Thd, NULL);
//close(gtestfd);
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
av_write_trailer(ofmt_ctx);
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
if (ofmt_ctx && !(ofmt_ctx->oformat->flags & AVFMT_NOFILE))
avio_closep(&ofmt_ctx->pb);
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
avformat_free_context(ofmt_ctx);
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
av_dict_free(&opt);
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
if (avio_out) {
av_freep(&avio_out->buffer);
av_freep(&avio_out);
}
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
avformat_close_input(&ifmt_ctx_v);
if (avio_in_v) {
av_freep(&avio_in_v->buffer);
av_freep(&avio_in_v);
}
printf("%s --line-- %d \n",__FUNCTION__, __LINE__);
avformat_close_input(&ifmt_ctx_a);
if (avio_in_a) {
av_freep(&avio_in_a->buffer);
av_freep(&avio_in_a);
}
printf("SaveThread exit ...........................for src=(%d) \n",src);
return;
}