#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include "h264.h"
#pragma comment(lib,"ws2_32.lib")
#define DEST_IP "192.168.1.6"
#define DEST_PORT 50001
#define IS_TCP 0
typedef struct
{
int startcodeprefix_len; //! 4 for parameter sets and first slice in picture, 3 for everything else (suggested)
unsigned len; //! Length of the NAL unit (Excluding the start code, which does not belong to the NALU)
unsigned max_size; //! Nal Unit Buffer size
int forbidden_bit; //! should be always FALSE
int nal_reference_idc; //! NALU_PRIORITY_xxxx
int nal_unit_type; //! NALU_TYPE_xxxx
char *buf; //! contains the first byte followed by the EBSP
unsigned short lost_packets; //! true, if packet loss is detected
} NALU_t;
typedef struct
{
unsigned magic : 8;
unsigned channel : 8;
unsigned rtp_len : 16;
} RILF;
FILE *bits = NULL; //!< the bit stream file
static int info2=0, info3=0;
RTP_FIXED_HEADER *rtp_hdr;
NALU_HEADER *nalu_hdr;
FU_INDICATOR *fu_ind;
FU_HEADER *fu_hdr;
RILF *rilf_hdr;
#ifdef WIN32
int init_winsock()
{
int Error;
WORD VersionRequested;
WSADATA WsaData;
VersionRequested=MAKEWORD(2,2);
Error=WSAStartup(VersionRequested,&WsaData); //start winsock2
if(Error!=0)
{
return 0;
}
else
{
if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
{
WSACleanup();
return 0;
}
}
return 1;
}
#endif
// Find start character 0x000001
static int find_startcode2 (unsigned char *Buf)
{
if (Buf[0]!=0 || Buf[1]!=0 || Buf[2] !=1) return 0;
else return 1;
}
// Find start character 0x00000001
static int find_startcode3 (unsigned char *Buf)
{
if (Buf[0]!=0 || Buf[1]!=0 || Buf[2] !=0 || Buf[3] !=1) return 0;
else return 1;
}
// Allocate memory space for NALU_t structure
NALU_t * alloc_nalu(int buffersize)
{
NALU_t *n;
if ((n = (NALU_t*)calloc (1, sizeof (NALU_t))) == NULL)
{
printf("alloc_nalu: n");
exit(0);
}
n->max_size=buffersize;
if ((n->buf = (char*)calloc (buffersize, sizeof (char))) == NULL)
{
free (n);
printf ("alloc_nalu: n->buf");
exit(0);
}
return n;
}
// Free
void free_nalu(NALU_t *n)
{
if (n)
{
if (n->buf)
{
free(n->buf);
n->buf=NULL;
}
free (n);
}
}
void open_media_file(const char *fn)
{
if (NULL == (bits=fopen(fn, "rb")))
{
printf("open file error\n");
exit(0);
}
}
// this function is to get a complete NALU and save it in the buf of NALU_t, get its length, fill in the F, IDC, and TYPE bits.
// And returns the number of bytes between the two starting characters, that is, the length of the NALU containing the prefix.
int get_annexb_nalu(NALU_t *nalu)
{
int pos = 0;
int StartCodeFound, rewind;
unsigned char *Buf;
if ((Buf = (unsigned char*)calloc (nalu->max_size , sizeof(char))) == NULL)
{
printf ("get_annexb_nalu: Could not allocate Buf memory\n");
}
nalu->startcodeprefix_len=3;
if (3 != fread (Buf, 1, 3, bits)) // Read 3 bytes from the bitstream
{
free(Buf);
return 0;
}
info2 = find_startcode2(Buf); // decide whether it is 0x000001
if (info2 != 1)
{
// If not, read another byte.
if (1 != fread(Buf+3, 1, 1, bits))// read one byte
{
free(Buf);
return 0;
}
info3 = find_startcode3 (Buf); // decide whether it is 0x00000001
if (info3 != 1)// If not, return -1
{
free(Buf);
return -1;
}
else
{
// If 0x00000001, the startcode prefix is 4 bytes.
pos = 4;
nalu->startcodeprefix_len = 4;
}
}
else
{
// If 0x000001, the startcode prefix is 3 bytes.
nalu->startcodeprefix_len = 3;
pos = 3;
}
// finding the next start character
StartCodeFound = 0;
info2 = 0;
info3 = 0;
while (!StartCodeFound)
{
if (feof(bits))
{
nalu->len = (pos-1)-nalu->startcodeprefix_len; //NALU unit length
memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);
nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
free(Buf);
return pos-1;
}
Buf[pos++] = fgetc (bits);
info3 = find_startcode3(&Buf[pos-4]); // decide whether it is 0x00000001
if (info3 != 1)
{
info2 = find_startcode2(&Buf[pos-3]); // decide whether it is 0x000001
}
StartCodeFound = (info2 == 1 || info3 == 1);
}
// Here, we have found another start code (and read length of startcode bytes more than we should
// have. Hence, go back in the file
rewind = (info3 == 1)? -4 : -3;
if (0 != fseek (bits, rewind, SEEK_CUR))
{
free(Buf);
printf("get_annexb_nalu: Cannot fseek in the bit stream file");
}
// Here the Start code, the complete NALU, and the next start code is in the Buf.
// The size of Buf is pos, pos+rewind are the number of bytes excluding the next
// start code, and (pos+rewind)-startcodeprefix_len is the size of the NALU excluding the start code
nalu->len = (pos+rewind)-nalu->startcodeprefix_len; // NALU length, excluding head.
memcpy (nalu->buf, &Buf[nalu->startcodeprefix_len], nalu->len);// Copy a complete NALU without copying the startcode prefix 0x000001 or 0x00000001.
nalu->forbidden_bit = nalu->buf[0] & 0x80; //1 bit
nalu->nal_reference_idc = nalu->buf[0] & 0x60; // 2 bit
nalu->nal_unit_type = (nalu->buf[0]) & 0x1f;// 5 bit
free(Buf);
return (pos+rewind);
}
// Output NALU length and TYPE
void dump(NALU_t *n)
{
if (!n) return;
//printf("a new nal:");
printf("len: %d ", n->len);
printf("nal_unit_type: %x\n", n->nal_unit_type);
}
int main(int argc, char* argv[])
{
NALU_t *n;
char* nalu_payload;
char sendbuf[1500];
int is_tcp = IS_TCP;
int offset = 0;
unsigned short seq_num = 0;
int bytes = 0;
#ifdef WIN32
SOCKET socket1;
#else
int socket1;
#endif
struct sockaddr_in server;
int len = sizeof(server);
int framerate = 30;
unsigned int timestamp_increse = 0, ts_current = 0;
timestamp_increse = (unsigned int)(90000.0 / framerate); //+0.5); // Timestamp, H264's video is set to 90000.
#ifdef WIN32
init_winsock();
#endif
open_media_file("test.264");
server.sin_family=AF_INET;
server.sin_port=htons(DEST_PORT);
server.sin_addr.s_addr=inet_addr(DEST_IP);
if (is_tcp)
socket1=socket(AF_INET, SOCK_STREAM, 0);
else
socket1=socket(AF_INET,SOCK_DGRAM,0);
int buflen = 1024 * 1024;
setsockopt(socket1, SOL_SOCKET, SO_SNDBUF, (char*)&buflen, sizeof(int));
setsockopt(socket1, SOL_SOCKET, SO_RCVBUF, (char*)&buflen, sizeof(int));
connect(socket1, (const sockaddr *)