int main() { bits = fopen("vivotest.264","r"); #if 1 ALooper looper1; MyRTSPHandler handler_rtsp; ARTPConnection handler_rtp; handler_rtp.setSource(&mysource); handler_rtsp.setRTPConnection(&handler_rtp); looper1.registerHandler(&handler_rtsp); looper1.registerHandler(&handler_rtp); looper1.start(); handler_rtsp.StartServer(); #endif #if 0 pthread_t idsend; pthread_t idget; int i,ret;b ret=pthread_create(&idsend,NULL,sendbuf,NULL); ret=pthread_create(&idget,NULL,getbuf,NULL); //sleep(1); void* status; pthread_join(idsend,&status); pthread_join(idget,&status); #endif #if 0 ARTPConnection* RTPConn = new ARTPConnection(); ALooper* looper1 = new ALooper; looper1->registerHandler(RTPConn); looper1->start(); struct sockaddr_in address;//处理网络通信的地址 int rtpsock; int rtcpsock; bzero(&address,sizeof(address)); address.sin_family=AF_INET; address.sin_addr.s_addr=inet_addr("127.0.0.1");//这里不一样 address.sin_port=htons(6789); RTPConn->setSource(&mysource); //MakePortPair(&rtpsock,&rtcpsock,address); printf("MakePortPair %d\n",MakePortPair(&rtpsock,&rtcpsock,address)); address.sin_family=AF_INET; address.sin_addr.s_addr=inet_addr("127.0.0.1");//这里不一样 address.sin_port=htons(6789); RTPConn->addStream(rtpsock,rtcpsock,0,&address); #endif sp<ABuffer> tmpbuf; int Len; int i=0; while(!handler_rtp.getStatus()) { usleep(2000); } while(feof(bits)==0) { if(mysource.inputQPop(tmpbuf)>=0) { Len = GetAnnexbNALU(tmpbuf); tmpbuf->setRange(0,Len); LOGI(LOG_TAG,"get a NALU length:%d NUM:%d\n",Len,i++); mysource.inputQPush(tmpbuf); } } sleep(10); LOGI(LOG_TAG,"END"); return 0; }
int main(int argc, char* argv[]) { //FILE *stream; //stream=fopen("Test.264", "wb"); OpenBitstreamFile("test2.h264");//打开264文件,并将文件指针赋给bits,在此修改文件名实现打开别的264文件。 NALU_t *n; char* nalu_payload; char sendbuf[1500]; unsigned short seq_num =0; //printf("seq_num=%d\n",seq_num);//added by int bytes=0; //InitWinsock(); //初始化套接字库 SOCKET socket1; struct sockaddr_in server; int len =sizeof(server); float framerate=25; unsigned int timestamp_increase=0,ts_current=0; timestamp_increase=(unsigned int)(90000.0 / framerate); //+0.5); server.sin_family=AF_INET; server.sin_port=htons(DEST_PORT); server.sin_addr.s_addr=inet_addr(DEST_IP); socket1=socket(AF_INET,SOCK_DGRAM,0); connect(socket1, (const struct sockaddr *)&server, len) ;//申请UDP套接字 n = AllocNALU(8000000);//为结构体nalu_t及其成员buf分配空间。返回值为指向nalu_t存储空间的指针 while(!feof(bits)) { GetAnnexbNALU(n);//每执行一次,文件的指针指向本次找到的NALU的末尾,下一个位置即为下个NALU的起始码0x000001 dump(n);//输出NALU长度和TYPE memset(sendbuf,0,1500);//清空sendbuf;此时会将上次的时间戳清空,因此需要ts_current来保存上次的时间戳值 //rtp固定包头,为12字节,该句将sendbuf[0]的地址赋给rtp_hdr,以后对rtp_hdr的写入操作将直接写入sendbuf。 rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0]; //设置RTP HEADER, rtp_hdr->payload = H264; //负载类型号, rtp_hdr->version = 2; //版本号,此版本固定为2 rtp_hdr->marker = 0; //标志位,由具体协议规定其值。 rtp_hdr->ssrc = htonl(10); //随机指定为10,并且在本RTP会话中全局唯一 // 当一个NALU小于1400字节的时候,采用一个单RTP包发送 if(n->len<=1400) { //设置rtp M 位; rtp_hdr->marker=1; rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1 //设置NALU HEADER,并将这个HEADER填入sendbuf[12] nalu_hdr =(NALU_HEADER*)&sendbuf[12]; //将sendbuf[12]的地址赋给nalu_hdr,之后对nalu_hdr的写入就将写入sendbuf中; nalu_hdr->F=n->forbidden_bit; nalu_hdr->NRI=n->nal_reference_idc>>5;//有效数据在n->nal_reference_idc的第6,7位,需要右移5位才能将其值赋给nalu_hdr->NRI。 nalu_hdr->TYPE=n->nal_unit_type; nalu_payload=&sendbuf[13];//同理将sendbuf[13]赋给nalu_payload memcpy(nalu_payload,n->buf+1,n->len-1);//去掉nalu头的nalu剩余内容写入sendbuf[13]开始的字符串。 ts_current=ts_current+timestamp_increase; rtp_hdr->timestamp=htonl(ts_current); bytes=n->len + 13 ; //获得sendbuf的长度,为nalu的长度(包含NALU头但除去起始前缀)加上rtp_header的固定长度12字节 send( socket1, sendbuf, bytes, 0 );//发送rtp包 //sleep(1); //fwrite(sendbuf,bytes, 1, stream); } else if(n->len>1400)
int rtp_send_file(int sockfd,struct sockaddr *addr) { printf("into the rtp_send_file...\n"); int rtp_number; //OpenBitstreamFile("./test.264");//打开264文件,并将文件指针赋给bits,在此修改文件名实现打开别的264文件。 OpenBitstreamFile("./slamtv60.264");//打开264文件,并将文件指针赋给bits,在此修改文件名实现打开别的264文件。 NALU_t *n; char* nalu_payload; char sendbuf[1500]; unsigned short seq_num =0; int bytes=0; float framerate=15; unsigned int timestamp_increse=0,ts_current=0; timestamp_increse=(unsigned int)(90000.0 / framerate); //+0.5); sleep(3); n = AllocNALU(80000000);//为结构体nalu_t及其成员buf分配空间。返回值为指向nalu_t存储空间的指针 sleep(3); printf("before the GetAnnexbNALU\n"); while(!feof(bits)) { GetAnnexbNALU(n);//每执行一次,文件的指针指向本次找到的NALU的末尾,下一个位置即为下个NALU的起始码0x000001 //dump(n);//输出NALU长度和TYPE memset(sendbuf,0,1500);//清空sendbuf;此时会将上次的时间戳清空,因此需要ts_current来保存上次的时间戳值 //rtp固定包头,为12字节,该句将sendbuf[0]的地址赋给rtp_hdr,以后对rtp_hdr的写入操作将直接写入sendbuf。 rtp_hdr =(RTP_FIXED_HEADER*)&sendbuf[0]; //设置RTP HEADER, rtp_hdr->payload = H264; //负载类型号, rtp_hdr->version = 2; //版本号,此版本固定为2 rtp_hdr->marker = 0; //标志位,由具体协议规定其值。 rtp_hdr->ssrc = htonl(10); //随机指定为10,并且在本RTP会话中全局唯一 // 当一个NALU小于1400字节的时候,采用一个单RTP包发送 if(n->len<=1400) { //设置rtp M 位; rtp_hdr->marker=1; rtp_hdr->seq_no = htons(seq_num ++); //序列号,每发送一个RTP包增1 //设置NALU HEADER,并将这个HEADER填入sendbuf[12] nalu_hdr =(NALU_HEADER*)&sendbuf[12]; //将sendbuf[12]的地址赋给nalu_hdr,之后对nalu_hdr的写入就将写入sendbuf中; nalu_hdr->F=n->forbidden_bit; nalu_hdr->NRI=n->nal_reference_idc>>5;//有效数据在n->nal_reference_idc的第6,7位,需要右移5位才能将其值赋给nalu_hdr->NRI。 nalu_hdr->TYPE=n->nal_unit_type; nalu_payload=&sendbuf[13];//同理将sendbuf[13]赋给nalu_payload memcpy(nalu_payload,n->buf+1,n->len-1);//去掉nalu头的nalu剩余内容写入sendbuf[13]开始的字符串。 ts_current=ts_current+timestamp_increse; rtp_hdr->timestamp=htonl(ts_current); bytes=n->len + 12 ; //获得sendbuf的长度,为nalu的长度(包含NALU头但除去起始前缀)加上rtp_header的固定长度12字节 // send( socket1, sendbuf, bytes, 0 );//发送rtp包 rtp_number = sendto(sockfd,sendbuf,bytes,0,addr,16); if(-1==rtp_number) { perror("len < 1400 rtp sendto error"); } else { printf("len < 1400 rtp_number = %d\n",rtp_number); } // Sleep(100); } else if(n->len>1400)
/*! ************************************************************************ * \brief * Reads new slice from bit_stream ************************************************************************ */ int read_new_slice() { NALU_t *nalu = AllocNALU(MAX_CODED_FRAME_SIZE); int current_header; int ret; int BitsUsedByHeader; Slice *currSlice = img->currentSlice; Bitstream *currStream; int newframe; int slice_id_a, slice_id_b, slice_id_c; int redundant_pic_cnt_a, redundant_pic_cnt_b, redundant_pic_cnt_c; long ftell_position, expected_slice_type; // int i; expected_slice_type = NALU_TYPE_DPA; while (1) { ftell_position = ftell(bits); if (input->FileFormat == PAR_OF_ANNEXB) ret=GetAnnexbNALU (nalu); else ret=GetRTPNALU (nalu); NALUtoRBSP(nalu); // printf ("nalu->len %d\n", nalu->len); if (ret < 0) printf ("Error while getting the NALU in file format %s, exit\n", input->FileFormat==PAR_OF_ANNEXB?"Annex B":"RTP"); if (ret == 0) { // printf ("read_new_slice: returning %s\n", "EOS"); if(expected_slice_type != NALU_TYPE_DPA) { /* oops... we found the next slice, go back! */ fseek(bits, ftell_position, SEEK_SET); FreeNALU(nalu); return current_header; } else return EOS; } // Got a NALU if (nalu->forbidden_bit) { printf ("Found NALU w/ forbidden_bit set, bit error? Let's try...\n"); } switch (nalu->nal_unit_type) { case NALU_TYPE_SLICE: case NALU_TYPE_IDR: img->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR); img->nal_reference_idc = nalu->nal_reference_idc; img->disposable_flag = (nalu->nal_reference_idc == NALU_PRIORITY_DISPOSABLE); currSlice->dp_mode = PAR_DP_1; currSlice->max_part_nr = 1; currSlice->ei_flag = 0; currStream = currSlice->partArr[0].bitstream; currStream->ei_flag = 0; currStream->frame_bitoffset = currStream->read_len = 0; memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1); currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1); // Some syntax of the Slice Header depends on the parameter set, which depends on // the parameter set ID of the SLice header. Hence, read the pic_parameter_set_id // of the slice header first, then setup the active parameter sets, and then read // the rest of the slice header BitsUsedByHeader = FirstPartOfSliceHeader(); UseParameterSet (currSlice->pic_parameter_set_id); BitsUsedByHeader+= RestOfSliceHeader (); FmoInit (active_pps, active_sps); init_lists(img->type, img->currentSlice->structure); reorder_lists (img->type, img->currentSlice); /* if (img->frame_num==1) // write a reference list { count ++; if (count==1) for (i=0; i<listXsize[0]; i++) write_picture(listX[0][i], p_out2); } */ if (img->MbaffFrameFlag) { init_mbaff_lists(); } if (img->currentSlice->structure!=0) { img->height /=2 ; img->height_cr /=2; } // From here on, active_sps, active_pps and the slice header are valid img->current_mb_nr = currSlice->start_mb_nr; if (img->tr_old != img->ThisPOC) { newframe=1; img->tr_old = img->ThisPOC; } else newframe = 0; if (newframe) current_header = SOP; else current_header = SOS; if(img->structure != img->structure_old) newframe |= 1; img->structure_old = img->structure; //! new stuff StW if(newframe || g_new_frame) { current_header = SOP; g_new_frame=0; } else current_header = SOS; if (active_pps->entropy_coding_mode_flag) { int ByteStartPosition = currStream->frame_bitoffset/8; if (currStream->frame_bitoffset%8 != 0) { ByteStartPosition++; } arideco_start_decoding (&currSlice->partArr[0].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type); } // printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS"); FreeNALU(nalu); return current_header; break; case NALU_TYPE_DPA: //! The state machine here should follow the same ideas as the old readSliceRTP() //! basically: //! work on DPA (as above) //! read and process all following SEI/SPS/PPS/PD/Filler NALUs //! if next video NALU is dpB, //! then read and check whether it belongs to DPA, if yes, use it //! else //! ; // nothing //! read and process all following SEI/SPS/PPS/PD/Filler NALUs //! if next video NALU is dpC //! then read and check whether it belongs to DPA (and DPB, if present), if yes, use it, done //! else //! use the DPA (and the DPB if present) /* LC: inserting the code related to DP processing, mainly copying some of the parts related to NALU_TYPE_SLICE, NALU_TYPE_IDR. */ if(expected_slice_type != NALU_TYPE_DPA) { /* oops... we found the next slice, go back! */ fseek(bits, ftell_position, SEEK_SET); FreeNALU(nalu); return current_header; } img->idr_flag = (nalu->nal_unit_type == NALU_TYPE_IDR); img->nal_reference_idc = nalu->nal_reference_idc; img->disposable_flag = (nalu->nal_reference_idc == NALU_PRIORITY_DISPOSABLE); currSlice->dp_mode = PAR_DP_3; currSlice->max_part_nr = 3; currSlice->ei_flag = 0; currStream = currSlice->partArr[0].bitstream; currStream->ei_flag = 0; currStream->frame_bitoffset = currStream->read_len = 0; memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1); currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1); BitsUsedByHeader = FirstPartOfSliceHeader(); UseParameterSet (currSlice->pic_parameter_set_id); BitsUsedByHeader += RestOfSliceHeader (); FmoInit (active_pps, active_sps); init_lists(img->type, img->currentSlice->structure); reorder_lists (img->type, img->currentSlice); if (img->MbaffFrameFlag) { init_mbaff_lists(); } if (img->currentSlice->structure!=0) { img->height /=2 ; img->height_cr /=2; } // From here on, active_sps, active_pps and the slice header are valid img->current_mb_nr = currSlice->start_mb_nr; if (img->tr_old != img->ThisPOC) { newframe=1; img->tr_old = img->ThisPOC; } else newframe = 0; if (newframe) current_header = SOP; else current_header = SOS; if(img->structure != img->structure_old) newframe |= 1; img->structure_old = img->structure; //! new stuff StW if(newframe || g_new_frame) { current_header = SOP; g_new_frame=0; } else current_header = SOS; /* LC: Now I need to read the slice ID, which depends on the value of redundant_pic_cnt_present_flag (pag.49). */ slice_id_a = ue_v("NALU:SLICE_A slice_idr", currStream); if (active_pps->redundant_pic_cnt_present_flag) redundant_pic_cnt_a = ue_v("NALU:SLICE_A redudand_pic_cnt", currStream); else redundant_pic_cnt_a = 0; if (active_pps->entropy_coding_mode_flag) { int ByteStartPosition = currStream->frame_bitoffset/8; if (currStream->frame_bitoffset%8 != 0) { ByteStartPosition++; } arideco_start_decoding (&currSlice->partArr[0].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type); } // printf ("read_new_slice: returning %s\n", current_header == SOP?"SOP":"SOS"); break; case NALU_TYPE_DPB: /* LC: inserting the code related to DP processing */ currStream = currSlice->partArr[1].bitstream; currStream->ei_flag = 0; currStream->frame_bitoffset = currStream->read_len = 0; memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1); currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1); slice_id_b = ue_v("NALU:SLICE_B slice_idr", currStream); if (active_pps->redundant_pic_cnt_present_flag) redundant_pic_cnt_b = ue_v("NALU:SLICE_B redudand_pic_cnt", currStream); else redundant_pic_cnt_b = 0; /* LC: Initializing CABAC for the current data stream. */ if (active_pps->entropy_coding_mode_flag) { int ByteStartPosition = currStream->frame_bitoffset/8; if (currStream->frame_bitoffset % 8 != 0) ByteStartPosition++; arideco_start_decoding (&currSlice->partArr[1].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type); } /* LC: resilience code to be inserted */ /* FreeNALU(nalu); */ /* return current_header; */ break; case NALU_TYPE_DPC: /* LC: inserting the code related to DP processing */ currStream = currSlice->partArr[2].bitstream; currStream->ei_flag = 0; currStream->frame_bitoffset = currStream->read_len = 0; memcpy (currStream->streamBuffer, &nalu->buf[1], nalu->len-1); currStream->code_len = currStream->bitstream_length = RBSPtoSODB(currStream->streamBuffer, nalu->len-1); slice_id_c = ue_v("NALU:SLICE_C slice_idr", currStream); if (active_pps->redundant_pic_cnt_present_flag) redundant_pic_cnt_c = ue_v("NALU:SLICE_C redudand_pic_cnt", currStream); else redundant_pic_cnt_c = 0; /* LC: Initializing CABAC for the current data stream. */ if (active_pps->entropy_coding_mode_flag) { int ByteStartPosition = currStream->frame_bitoffset/8; if (currStream->frame_bitoffset % 8 != 0) ByteStartPosition++; arideco_start_decoding (&currSlice->partArr[2].de_cabac, currStream->streamBuffer, ByteStartPosition, &currStream->read_len, img->type); } /* LC: resilience code to be inserted */ FreeNALU(nalu); return current_header; break; case NALU_TYPE_SEI: printf ("read_new_slice: Found NALU_TYPE_SEI, len %d\n", nalu->len); InterpretSEIMessage(nalu->buf,nalu->len,img); break; case NALU_TYPE_PPS: ProcessPPS(nalu); break; case NALU_TYPE_SPS: ProcessSPS(nalu); break; case NALU_TYPE_PD: // printf ("read_new_slice: Found 'Access Unit Delimiter' NAL unit, len %d, ignored\n", nalu->len); break; case NALU_TYPE_EOSEQ: // printf ("read_new_slice: Found 'End of Sequence' NAL unit, len %d, ignored\n", nalu->len); break; case NALU_TYPE_EOSTREAM: // printf ("read_new_slice: Found 'End of Stream' NAL unit, len %d, ignored\n", nalu->len); break; case NALU_TYPE_FILL: printf ("read_new_slice: Found NALU_TYPE_FILL, len %d\n", nalu->len); printf ("Skipping these filling bits, proceeding w/ next NALU\n"); break; default: printf ("Found NALU type %d, len %d undefined, ignore NALU, moving on\n", nalu->nal_unit_type, nalu->len); } } FreeNALU(nalu); return current_header; }