c - Streaming H.264 over RTP (Raspberry Pi) -
c - Streaming H.264 over RTP (Raspberry Pi) -
i need help using rtp protocol streaming h.264 video. have raspberry pi(b+) , photographic camera module. raspberry pi has hardware encoder h.264.
however, player can't play rtp streams: video have delay , image bad :
i can't understand problem.
there stream h.264 :
[sps] [pps] [i-frame] [p-frame] [p-frame] [p-frame] .... [sps] [pps] [i-frame] .... this stream place in separate rtp packets. log of vlc while playing:
[h264 @ 0x90bba80] error while decoding mb 19 14, bytestream (-3) [h264 @ 0x90bba80] concealing 50 dc, 50 ac, 50 mv errors [h264 @ 0x90bb680] error while decoding mb 19 14, bytestream (-3) [h264 @ 0x90bb680] concealing 50 dc, 50 ac, 50 mv errors [h264 @ 0x90bb680] error while decoding mb 19 14, bytestream (-3) [h264 @ 0x90bb680] concealing 50 dc, 50 ac, 50 mv errors for access hardware encoder utilize openmax. part of code encoder:
omx_init_structure(ep->encoder_portdef); ep->encoder_portdef.nportindex = 201; if((r = omx_getparameter(ctx->encoder, omx_indexparamportdefinition, &ep->encoder_portdef)) != omx_errornone) die("failed port definition encoder output port 201"); ep->encoder_portdef.format.video.nframewidth = cp->camera_portdef.format.video.nframewidth; ep->encoder_portdef.format.video.nframeheight = cp->camera_portdef.format.video.nframeheight; ep->encoder_portdef.format.video.xframerate = cp->camera_portdef.format.video.xframerate; ep->encoder_portdef.format.video.nstride = cp->camera_portdef.format.video.nstride; ep->encoder_portdef.format.video.ecompressionformat = omx_video_codingavc; ep->encoder_portdef.format.video.nbitrate = dp->video.bitrate; if((r = omx_setparameter(ctx->encoder, omx_indexparamportdefinition, &ep->encoder_portdef)) != omx_errornone) die("failed set port definition encoder output port 201"); omx_init_structure(ep->bitrate); ep->bitrate.econtrolrate = omx_video_controlratevariable; ep->bitrate.ntargetbitrate = ep->encoder_portdef.format.video.nbitrate; ep->bitrate.nportindex = 201; if((r = omx_setparameter(ctx->encoder, omx_indexparamvideobitrate, &ep->bitrate)) != omx_errornone) die("failed set bitrate encoder output port 201"); omx_video_config_avcintraperiod idr; omx_init_structure(idr); idr.nportindex = 201; if((r=omx_getparameter(ctx->encoder, omx_indexconfigvideoavcintraperiod, &idr)) != omx_errornone) die("failed encoder params\n"); omx_init_structure(idr); idr.nportindex = 201; idr.nidrperiod = 30; if((r=omx_setparameter(ctx->encoder, omx_indexconfigvideoavcintraperiod, &idr)) != omx_errornone) die("failed encoder params\n"); resulting info encoder send function, remove starting code (00 00 00 01):
error = omx_fillthisbuffer (encoder.handle, ctx.encoder_ppbuffer_out); .................. buf = ctx.encoder_ppbuffer_out->pbuffer; len = ctx.encoder_ppbuffer_out->nfilledlen; send_data_to_rtp((uint8_t*)&buf[4], len-4, 30); description function packing rtp:
// titles #define buf_size 1500 #define rtp_payload_max_size 1400 /* rtp header */ typedef struct{ /* 1 byte */ uint8_t csrc_len: 4; uint8_t extension: 1; uint8_t padding: 1; uint8_t version: 2; /* 2 byte */ uint8_t payload_type: 7; uint8_t marker: 1; /* 3-4 */ uint16_t seq_no; /* 5-8 */ uint32_t timestamp; /* 9-12 */ uint32_t ssrc; }__attribute__ ((packed)) rtp_header; typedef struct { uint8_t type: 5; uint8_t nri: 2; uint8_t f: 1; }__attribute__ ((packed)) nalu_header; typedef struct { uint8_t type: 5; uint8_t nri: 2; uint8_t f: 1; } __attribute__ ((packed)) fu_indicator; typedef struct { uint8_t type: 5; uint8_t r: 1; uint8_t e: 1; uint8_t s: 1; } __attribute__ ((packed)) fu_header; // create packet static void send_data_to_rtp(uint8_t *data, int len, int framerate) { static uint8_t sendbuf[buf_size]; static uint32_t ts_current = 0; static uint16_t seq_num = 0; static uint16_t pack_num, last_pack_size, current_pack; uint8_t *nalu_playload; /* rtp header */ rtp_header *rtp_hdr; /* nalu header */ nalu_header *nalu_hdr; fu_indicator *fu_ind; fu_header *fu_hdr; ts_current += (90000 / framerate); memset(sendbuf, 0, sizeof(sendbuf)); rtp_hdr = (rtp_header*)&sendbuf[0]; rtp_hdr->version = 2; rtp_hdr->marker = 0; rtp_hdr->csrc_len = 0; rtp_hdr->extension = 0; rtp_hdr->padding = 0; rtp_hdr->ssrc = htonl(ssrc_num); rtp_hdr->payload_type = type_h264; rtp_hdr->timestamp = htonl(ts_current); if (len <= rtp_payload_max_size) { rtp_hdr->marker = 1; rtp_hdr->seq_no = htons(++seq_num); nalu_hdr = (nalu_header*)&sendbuf[12]; nalu_hdr->type = data[0] & 0x1f; nalu_hdr->f = data[0] & 0x80; nalu_hdr->nri = data[0] & 0x60 >> 5; nalu_playload = (uint8_t*)&sendbuf[13]; memcpy(nalu_playload, info + 1, len-1); send_data_client(sendbuf, len + 13); } else { pack_num = (len % rtp_payload_max_size) ? (len / rtp_payload_max_size + 1) : (len / rtp_payload_max_size); /* info size in lastly packege */ last_pack_size = (len % rtp_payload_max_size) ? (len % rtp_payload_max_size) : (rtp_payload_max_size); current_pack = 0; fu_ind = (fu_indicator *)&sendbuf[12]; fu_ind->f = data[0] & 0x80; fu_ind->nri = (data[0] & 0x60) >> 5; fu_ind->type = 28; fu_hdr = (fu_header *)&sendbuf[13]; fu_hdr->type = data[0] & 0x1f; while (current_pack < pack_num) { rtp_hdr->seq_no = htons(++seq_num); /* first packet */ if(current_pack == 0) { fu_hdr->s = 1, fu_hdr->e = 0, fu_hdr->r = 0; rtp_hdr->marker = 0; nalu_playload = (uint8_t*)&sendbuf[14]; memset(nalu_playload, 0, rtp_payload_max_size); memcpy(nalu_playload, info + 1, rtp_payload_max_size); send_data_client(sendbuf, rtp_payload_max_size + 14); } else if(current_pack < pack_num - 1){ fu_hdr->s = 0, fu_hdr->e = 0, fu_hdr->r = 0; rtp_hdr->marker = 0; nalu_playload = (uint8_t*)&sendbuf[14]; memset(nalu_playload, 0, rtp_payload_max_size); memcpy(nalu_playload, info + (current_pack * rtp_payload_max_size) + 1, rtp_payload_max_size); send_data_client(sendbuf, rtp_payload_max_size + 14); /* lastly packet */ } else { rtp_hdr->marker = 1; nalu_playload = (uint8_t*)&sendbuf[14]; fu_hdr->s = 0, fu_hdr->e = 1, fu_hdr->r = 0; memset(nalu_playload, 0, rtp_payload_max_size); memcpy(nalu_playload, info + (current_pack * rtp_payload_max_size) + 1, last_pack_size - 1); send_data_client(sendbuf, last_pack_size - 1 + 14); } current_pack += 1; } } } // write info socket static void send_data_client(uint8_t *send_buf, size_t len_sendbuf) { sendto(socket_fd, send_buf, len_sendbuf, 0, (struct sockaddr *)&addr,sizeof(addr)); } c raspberry-pi h.264 rtp openmax
Comments
Post a Comment