00001
00015 #include "global.h"
00016 #include "annexb.h"
00017 #include "memalloc.h"
00018
00019 static int BitStreamFile = -1;
00020 static const unsigned int IOBUFFERSIZE = 65536;
00021 static byte *iobuffer;
00022 static byte *iobufferread;
00023 static unsigned int bytesinbuffer;
00024 static int is_eof;
00025
00026 static int IsFirstByteStreamNALU = 1;
00027
00028
00035 static inline int getChunk()
00036 {
00037 unsigned int readbytes = read (BitStreamFile, iobuffer, IOBUFFERSIZE);
00038 if (0==readbytes)
00039 {
00040 is_eof = TRUE;
00041 return 0;
00042 }
00043
00044 bytesinbuffer = readbytes;
00045 iobufferread = iobuffer;
00046 return readbytes;
00047 }
00048
00049
00056 static inline byte getfbyte()
00057 {
00058 if (0==bytesinbuffer)
00059 {
00060 if (0 == getChunk())
00061 return 0;
00062 }
00063 bytesinbuffer--;
00064 return (*iobufferread++);
00065 }
00066
00067
00084 static inline int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
00085 {
00086 int i;
00087
00088 for (i = 0; i < zeros_in_startcode; i++)
00089 {
00090 if(*(Buf++) != 0)
00091 {
00092 return 0;
00093 }
00094 }
00095
00096 if(*Buf != 1)
00097 return 0;
00098
00099 return 1;
00100 }
00101
00102
00122 static int nextstartcodebytes = 0;
00123
00124 int GetAnnexbNALU (NALU_t *nalu)
00125 {
00126 int i;
00127 int info2 = 0, info3 = 0, pos = 0;
00128 int StartCodeFound = 0;
00129 static byte *Buf, *pBuf;
00130 int LeadingZero8BitsCount = 0;
00131
00132 if ((Buf = (byte*) calloc (nalu->max_size , sizeof(char))) == NULL)
00133 no_mem_exit("GetAnnexbNALU: Buf");
00134
00135 pBuf = Buf;
00136
00137 if (nextstartcodebytes != 0)
00138 {
00139 for (i=0; i<nextstartcodebytes-1; i++)
00140 {
00141 (*pBuf++) = 0;
00142 pos++;
00143 }
00144 (*pBuf++) = 1;
00145 pos++;
00146 }
00147 else
00148 {
00149 while(!is_eof)
00150 {
00151 pos++;
00152 if ((*(pBuf++)= getfbyte())!= 0)
00153 break;
00154 }
00155 }
00156 if(is_eof == TRUE)
00157 {
00158 free (Buf);
00159 if(pos==0)
00160 {
00161 return 0;
00162 }
00163 else
00164 {
00165 printf( "GetAnnexbNALU can't read start code\n");
00166 return -1;
00167 }
00168 }
00169
00170 if(*(pBuf - 1) != 1 || pos < 3)
00171 {
00172 printf ("GetAnnexbNALU: no Start Code at the beginning of the NALU, return -1\n");
00173 free (Buf);
00174 return -1;
00175 }
00176
00177 if (pos == 3)
00178 {
00179 nalu->startcodeprefix_len = 3;
00180 }
00181 else
00182 {
00183 LeadingZero8BitsCount = pos - 4;
00184 nalu->startcodeprefix_len = 4;
00185 }
00186
00187
00188
00189
00190 if(!IsFirstByteStreamNALU && LeadingZero8BitsCount > 0)
00191 {
00192 printf ("GetAnnexbNALU: The leading_zero_8bits syntax can only be present in the first byte stream NAL unit, return -1\n");
00193 free (Buf);
00194 return -1;
00195 }
00196
00197 LeadingZero8BitsCount = pos;
00198 IsFirstByteStreamNALU = 0;
00199
00200 while (!StartCodeFound)
00201 {
00202 if (is_eof == TRUE)
00203 {
00204 pBuf -= 2;
00205 while(*(pBuf--)==0)
00206 pos--;
00207
00208 nalu->len = (pos - 1) - LeadingZero8BitsCount;
00209 memcpy (nalu->buf, Buf + LeadingZero8BitsCount, nalu->len);
00210 nalu->forbidden_bit = (*(nalu->buf) >> 7) & 1;
00211 nalu->nal_reference_idc = (*(nalu->buf) >> 5) & 3;
00212 nalu->nal_unit_type = (*(nalu->buf)) & 0x1f;
00213 nextstartcodebytes = 0;
00214
00215
00216
00217 #if TRACE
00218 fprintf (p_trace, "\n\nLast NALU in File\n\n");
00219 fprintf (p_trace, "Annex B NALU w/ %s startcode, len %d, forbidden_bit %d, nal_reference_idc %d, nal_unit_type %d\n\n",
00220 nalu->startcodeprefix_len == 4?"long":"short", nalu->len, nalu->forbidden_bit, nalu->nal_reference_idc, nalu->nal_unit_type);
00221 fflush (p_trace);
00222 #endif
00223
00224 free (Buf);
00225 return (pos - 1);
00226 }
00227
00228 pos++;
00229 *(pBuf ++) = getfbyte();
00230 info3 = FindStartCode(pBuf - 4, 3);
00231 if(info3 != 1)
00232 {
00233 info2 = FindStartCode(pBuf - 3, 2);
00234 StartCodeFound = (info2 == 1);
00235 }
00236 else
00237 StartCodeFound = 1;
00238 }
00239
00240
00241
00242 if(info3 == 1)
00243 {
00244 pBuf -= 5;
00245 while(*(pBuf--) == 0)
00246 pos--;
00247 nextstartcodebytes = 4;
00248 }
00249 else if (info2 == 1)
00250 nextstartcodebytes = 3;
00251 else
00252 {
00253 printf(" Panic: Error in next start code search \n");
00254 free (Buf);
00255 return -1;
00256 }
00257
00258 pos -= nextstartcodebytes;
00259
00260
00261
00262
00263
00264
00265
00266 nalu->len = pos - LeadingZero8BitsCount;
00267 memcpy (nalu->buf, Buf + LeadingZero8BitsCount, nalu->len);
00268 nalu->forbidden_bit = (*(nalu->buf) >> 7) & 1;
00269 nalu->nal_reference_idc = (*(nalu->buf) >> 5) & 3;
00270 nalu->nal_unit_type = (*(nalu->buf)) & 0x1f;
00271 nalu->lost_packets = 0;
00272
00273
00274 #if TRACE
00275 fprintf (p_trace, "\n\nAnnex B NALU w/ %s startcode, len %d, forbidden_bit %d, nal_reference_idc %d, nal_unit_type %d\n\n",
00276 nalu->startcodeprefix_len == 4?"long":"short", nalu->len, nalu->forbidden_bit, nalu->nal_reference_idc, nalu->nal_unit_type);
00277 fflush (p_trace);
00278 #endif
00279
00280 free (Buf);
00281 return (pos);
00282 }
00283
00284
00293 void OpenAnnexBFile (char *fn)
00294 {
00295 if (NULL != iobuffer)
00296 {
00297 error ("OpenAnnexBFile: tried to open Annex B file twice",500);
00298 }
00299 if ((BitStreamFile = open(fn, OPENFLAGS_READ)) == -1)
00300 {
00301 snprintf (errortext, ET_SIZE, "Cannot open Annex B ByteStream file '%s'", fn);
00302 error(errortext,500);
00303 }
00304 iobuffer = malloc (IOBUFFERSIZE * sizeof (byte));
00305 if (NULL == iobuffer)
00306 {
00307 error ("OpenAnnexBFile: cannot allocate IO buffer",500);
00308 }
00309 is_eof = FALSE;
00310 getChunk();
00311 }
00312
00313
00320 void CloseAnnexBFile()
00321 {
00322 if (BitStreamFile != -1)
00323 {
00324 close(BitStreamFile);
00325 BitStreamFile = - 1;
00326 }
00327 free (iobuffer);
00328 iobuffer = NULL;
00329 }
00330