1 /***************************************************************************
2                           ADM_infoextractor
3                              -------------------
4            - extract additionnal info from header (mp4/h263)
5 **************************************************************************/
6 /***************************************************************************
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  ***************************************************************************/
14 
15 #ifdef _MSC_VER
16 #    include <malloc.h>
17 #endif
18 
19 #include "ADM_default.h"
20 
21 extern "C"
22 {
23 #include "libavcodec/parser.h"
24 #include "libavcodec/avcodec.h"
25 #include "libavcodec/ff_spsinfo.h"
26 #include "libavutil/mem.h"
27 extern int ff_h264_info(AVCodecParserContext *parser, int ticksPerFrame, ffSpsInfo *ndo);
28 }
29 
30 #include "ADM_Video.h"
31 
32 #include "fourcc.h"
33 //#include "ADM_mp4.h"
34 
35 #include "ADM_getbits.h"
36 #include "ADM_videoInfoExtractor.h"
37 #include "ADM_h264_tag.h"
38 
39 
40 //#define ANNEX_B_DEBUG
41 
42 #if defined(ANNEX_B_DEBUG)
43 #define aprintf ADM_info
44 #define check isNalValid
45 #else
46 #define aprintf(...) {}
47 #define check(...) {}
48 #endif
49 
50 #if 0
51 #define seiprintf ADM_info
52 #else
53 #define seiprintf(...) {}
54 #endif
55 
56 extern bool ADM_findAnnexBStartCode(uint8_t *start, uint8_t *end, uint8_t *outstartcode,
57                 uint32_t *offset, bool *fivebytes);
58 
59 /**
60     \fn ADM_getH264SpsPpsFromExtraData
61     \brief Returns a copy of PPS/SPS extracted from extrdata
62 */
ADM_SPSannexBToMP4(uint32_t dataLen,uint8_t * incoming,uint32_t * outLen,uint8_t * outData)63 bool ADM_SPSannexBToMP4(uint32_t dataLen,uint8_t *incoming,
64                                     uint32_t *outLen, uint8_t *outData)
65 {
66     int p;
67     if(dataLen>200)
68     {
69         ADM_warning("SPS TOO LONG\n");
70         return false;
71     }
72     // 01
73     // 4d 40 1f ff
74     // e1 00 1b 67
75     // 4d 40 1f f6
76     // 02 80 2d
77 
78     outData[0]=1;
79     outData[1]=0x4d;
80     outData[2]=0x40;
81     outData[3]=0x1f;
82     outData[4]=0xff;
83     outData[5]=0xe1; // 1 stream
84     outData[6]=0; // Len MSB
85     outData[7]=0; // Len LSB, should fit in 1 byte...
86     outData[8]=0x67; // Len LSB, should fit in 1 byte...
87 #if 1
88     memcpy(outData+9,incoming,dataLen);
89     p=dataLen;
90 #else
91     p=ADM_unescapeH264(dataLen,incoming,outData+9) ;
92 #endif
93     outData[7]=(p+1); // Len LSB, should fit in 1 byte...
94     outData[6]=(p+1)>>8; // MSB : And no, does not always fit
95     *outLen= p+9;
96     return true;
97 }
98 
99 /**
100     \fn ADM_getNalSizeH264
101     \brief extract NALU length size from avcC header
102 */
ADM_getNalSizeH264(uint8_t * extra,uint32_t len)103 uint32_t ADM_getNalSizeH264(uint8_t *extra, uint32_t len)
104 {
105     if(len < 9)
106     {
107         ADM_warning("Invalid H.264 extradata length %u\n",len);
108         return 0;
109     }
110     if(extra[0] != 1)
111     {
112         ADM_warning("Invalid H.264 extradata\n");
113         return 0;
114     }
115     return (extra[4] & 3) + 1;
116 }
117 
118 /**
119     \fn ADM_escapeH264
120     \brief Add escape stuff
121 
122 */
ADM_escapeH264(uint32_t len,uint8_t * in,uint8_t * out)123 uint32_t ADM_escapeH264 (uint32_t len, uint8_t * in, uint8_t * out)
124 {
125   uint32_t outlen = 0;
126   uint8_t *tail = in + len;
127   if (len < 2)
128     return 0;
129   while (in < tail-1 )
130     {
131       if (!in[0] && !in[1])
132     {
133       out[0] = 0;
134       out[1] = 0;
135           out[2] = 3;
136       out += 3;
137       outlen += 3;
138       in += 2;
139           continue;
140     }
141       *out++ = *in++;
142       outlen++;
143     }
144   // copy last bytes
145   uint32_t left = tail - in;
146   memcpy (out, in, left);
147   outlen += left;
148   return outlen;
149 
150 }
151 /**
152     \fn unescapeH264
153     \brief Remove escape stuff
154 
155 */
ADM_unescapeH264(uint32_t len,uint8_t * in,uint8_t * out)156 uint32_t ADM_unescapeH264 (uint32_t len, uint8_t * in, uint8_t * out)
157 {
158   if (len < 3)
159     return 0;
160   uint8_t *offset = in;
161   uint8_t *firstOut=out;
162   uint32_t outlen = 0;
163   uint8_t *tail = in + len;
164   uint8_t *border=tail-3;
165 
166   while (in < border)
167   {
168         if(in[1]) // cannot be 00 00 nor the next one
169         {
170           in += 2;
171           continue;
172         }
173         if(!in[0] && !in[1] && in[2] == 3)
174         {
175           uint32_t copy = in - offset + 2;
176           memcpy(out, offset, copy);
177           out += copy;
178           in += 3;
179           offset = in;
180           continue;
181         }
182         in++;
183   }
184   outlen=(int)(out-firstOut);
185   // copy last bytes
186   uint32_t left = tail - offset;
187   memcpy (out, offset, left);
188   outlen += left;
189   return outlen;
190 
191 }
192 /**
193     \fn hrd
194     \brief decode hdr_parameters
195 */
hrd(getBits & bits)196 static int hrd(getBits &bits)
197 {
198     //ADM_warning("hdr not implemented\n");
199     int count = bits.getUEG();
200 
201     bits.get(4);    // bitRateScale
202     bits.get(4);    // scale
203 
204     for(int i = 0; i <= count; i++)
205     {
206         bits.getUEG();    // bitrate
207         bits.getUEG();  // sizeMinus1
208         bits.get(1);    // cbrFlag
209     }
210 
211     bits.get(5);    // initialRemovalDelay
212 
213     int removalDelay=bits.get(5);
214     int outputDelay=bits.get(5);
215 
216     bits.get(5);    // timeOffset
217 
218     return removalDelay+outputDelay+2 ;
219 }
220 /**
221         \fn extractVUIInfo
222 */
extractVUIInfo(getBits & bits,ADM_SPSInfo * spsinfo)223 static uint8_t  extractVUIInfo (getBits &bits, ADM_SPSInfo *spsinfo)
224 {
225   if (bits.get(1))
226     {
227       unsigned int aspect_ratio_information = bits.get( 8);
228 
229       if (aspect_ratio_information == 255)
230     {
231       spsinfo->darNum = bits.get( 16);
232       spsinfo->darDen = bits.get( 16);
233     }
234       else if (aspect_ratio_information <
235            sizeof (pixel_aspect) / sizeof (*pixel_aspect))
236     {
237       spsinfo->darNum = pixel_aspect[aspect_ratio_information].num;
238       spsinfo->darDen = pixel_aspect[aspect_ratio_information].den;
239     }
240     }
241 
242   if (bits.get(1))        // overscan
243     bits.get(1);
244 
245   if (bits.get(1))        // vsp_color
246     {
247       bits.get( 4);
248 
249       if (bits.get(1))
250     {
251         bits.get( 8);
252         bits.get( 8);
253         bits.get( 8);
254     }
255     }
256 
257   if (bits.get(1))        // chroma
258     {
259       bits.getUEG();
260       bits.getUEG();
261     }
262 
263   if (bits.get(1))        // timing
264     {
265       uint32_t timeinc_unit = bits.get( 32);
266       uint32_t timeinc_resolution = bits.get( 32);
267       uint32_t fixed_fps = bits.get(1);
268       ADM_info("Time unit =%d/%d\n",(int)timeinc_unit,(int)timeinc_resolution);
269       if (timeinc_unit > 0 && timeinc_resolution > 0)
270         spsinfo->fps1000 =  (uint32_t) (((float) timeinc_resolution / (float) timeinc_unit) *    1000);
271 /* No!
272       if (fixed_fps)
273     *fps1000 /= 2;
274 */
275     }
276     uint32_t f=0;
277     spsinfo->CpbDpbToSkip=0;
278     if(bits.get(1)) // nal_hrd_param
279     {
280         f++;
281         spsinfo->CpbDpbToSkip+=hrd(bits);
282     }
283     if(bits.get(1)) // vcl_hrd_param
284     {
285         f++;
286         spsinfo->CpbDpbToSkip+=hrd(bits);
287     }
288     if(f) bits.get(1); // low delay flag
289 
290 
291     spsinfo->hasStructInfo=bits.get(1) | spsinfo->CpbDpbToSkip;
292     // Has struct info in SEI, see D2.2
293 
294   return 1;
295 }
296 /**
297         \fn decodeOnMatrix
298         \brief borrowed from ffmpeg
299 */
decodeOneMatrix(int count,getBits & bits)300 bool decodeOneMatrix(int count,getBits &bits)
301 {
302         if(!bits.get(1))
303         {
304                 return true;
305         }
306 
307         int i, last = 8, next = 8;
308         for(i=0;i<count;i++)
309         {
310          if(next)
311             next = (last + bits.getUEG()) & 0xff;
312          if(!i && !next)
313          { /* matrix not written, we use the preset one */
314             return true;
315          }
316          //last = factors[scan[i]] = next ? next : last;
317     }
318     return true;
319 
320 }
321 /**
322         \fn decodeScalingMatrices
323 */
decodeScalingMatrices(getBits & bits)324 bool          decodeScalingMatrices(getBits &bits)
325 {
326         decodeOneMatrix(16,bits);
327         decodeOneMatrix(16,bits);
328         decodeOneMatrix(16,bits);
329         decodeOneMatrix(16,bits);
330         decodeOneMatrix(16,bits);
331         decodeOneMatrix(16,bits);
332         decodeOneMatrix(64,bits);
333         decodeOneMatrix(64,bits);
334         return true;
335 }
336 
337 /**
338     \fn extractSPSInfo
339     \brief Extract info from H264 SPS
340     See 7.3.2.1 of 14496-10
341 */
extractSPSInfo_internal(uint8_t * data,uint32_t len,ADM_SPSInfo * spsinfo)342 uint8_t extractSPSInfo_internal (uint8_t * data, uint32_t len, ADM_SPSInfo *spsinfo)
343 {
344 
345   uint32_t profile, constraint, level, pic_order_cnt_type, w, h, mbh,
346     frame_mbs_only;
347   uint32_t frame_cropping_flag;
348   uint32_t chroma_format_idc = 1; // this defaults to 1 when it's missing
349   uint32_t separate_colour_plane_flag = 0;
350   uint32_t chroma_array_type = 0;
351   uint8_t *buf = new uint8_t[len];
352   uint32_t outlen;
353   uint32_t id, dum;
354 
355     ADM_assert(spsinfo);
356     memset(spsinfo,0,sizeof(*spsinfo));
357 
358 
359   outlen = ADM_unescapeH264 (len, data, buf);
360   getBits bits(outlen,buf);
361   delete [] buf;
362 
363   profile = bits.get(8);
364   constraint = bits.get( 8) >> 5;
365   level = bits.get( 8);
366   id = bits.getUEG();    // Seq parameter set id
367   printf ("[H264]Profile : %u, Level :%u, SPSid:%u\n", profile, level, id);
368   if (profile >= 100)        // ?? Borrowed from H264.C/FFMPEG
369     {
370       printf ("[H264]Warning : High profile\n");
371       chroma_format_idc = bits.getUEG();
372       if (chroma_format_idc == 3)    //chroma_format_idc
373         separate_colour_plane_flag = bits.get(1);        //residual_color_transform_flag
374       bits.getUEG();    //bit_depth_luma_minus8
375       bits.getUEG();    //bit_depth_chroma_minus8
376       bits.get(1);        // Transform bypass
377       if (bits.get(1))    // Scaling matrix
378       {
379         printf ("[H264] Scaling matrix present\n");
380           decodeScalingMatrices(bits);
381       }
382     }
383 
384     if ( separate_colour_plane_flag == 0 )
385         chroma_array_type = chroma_format_idc;
386 
387   dum = bits.getUEG();    // log2_max_frame_num_minus4
388   printf ("[H264]Log2maxFrame-4:%u\n", dum);
389   pic_order_cnt_type = bits.getUEG();
390   printf ("[H264]Pic Order Cnt Type:%u\n", pic_order_cnt_type);
391   if (!pic_order_cnt_type)    // pic_order_cnt_type
392     {
393       dum = bits.getUEG();    //log2_max_pic_order_cnt_lsb_minus4
394       printf ("[H264]Log2maxPix-4:%u\n", dum);
395     }
396   else
397     {
398       if (pic_order_cnt_type == 1)
399     {
400       bits.get(1);    //delta_pic_order_always_zero_flag
401       bits.getSEG();    //offset_for_non_ref_pic
402       bits.getSEG();    // offset_for_top_to_bottom_field
403       int i = bits.getUEG() ;    //num_ref_frames_in_pic_order_cnt_cycle
404 
405       for (int j = 0; j < i; j++)
406         {
407           bits.getSEG();
408         }
409     }
410       else if (pic_order_cnt_type != 2)
411     {
412       printf ("Error in SPS\n");
413       return 0;
414     }
415     }
416   dum = bits.getUEG();    //num_ref_frames
417   printf ("[H264] # of ref frames : %u\n", dum);
418   bits.get(1);        // gaps_in_frame_num_value_allowed_flag
419   w = bits.getUEG() + 1;    //pic_width_in_mbs_minus1
420 
421   mbh = bits.getUEG() + 1;
422   frame_mbs_only = bits.get(1);
423   h = (2 - frame_mbs_only) * mbh;    //pic_height_in_mbs_minus1
424 
425   printf ("[H264] Width in mb -1  :%d\n", w);
426   printf ("[H264] Height in mb -1 :%d\n", h);
427 
428   spsinfo->width = w * 16;
429   spsinfo->height = h * 16;
430 
431   if (!frame_mbs_only)
432     bits.get(1);
433 
434   bits.get(1);
435 
436     frame_cropping_flag = bits.get(1);
437      if (frame_cropping_flag)
438     {
439         // The tests could probably be done more simply but the following is per the spec.
440         uint32_t cl, cr, ct, cb;
441         int cux = 1; // x units
442         int cuy = 2 - frame_mbs_only; // y units
443         if ( chroma_array_type > 0 ) {
444             switch( chroma_format_idc ) {
445             case 1:
446                 cux = 2;
447                 cuy = 2 * ( 2 - frame_mbs_only );
448                 break;
449             case 2:
450                 cux = 2;
451                 cuy = 1 * ( 2 - frame_mbs_only );
452                 break;
453             case 3:
454                 cux = 1;
455                 cuy = 1 * ( 2 - frame_mbs_only );
456                 break;
457             }
458         }
459         cl = bits.getUEG() * cux;
460         cr = bits.getUEG() * cux;
461         ct = bits.getUEG() * cuy;
462         cb = bits.getUEG() * cuy;
463         spsinfo->width -= cl; // reduce dims based on crop values
464         spsinfo->width -= cr;
465         spsinfo->height -= ct;
466         spsinfo->height -= cb;
467         printf ("[H264] Has cropping of l:%d  r:%d  t:%d  b:%d\n", cl, cr, ct, cb);
468     }
469 
470   if (bits.get(1))
471     {
472       extractVUIInfo (bits, spsinfo);
473 //      printf ("[H264] Fps %" LU ", a.r. %" LU ",%" LU "\n", spsinfo->fps1000, spsinfo->darNum,  spsinfo->darDen);
474     }
475   else
476     {
477       printf ("[H264] Unknown FPS, setting 25\n");
478       spsinfo->fps1000 = 25000;
479     }
480   return 1;
481 }
482 
483 /**
484     \fn getInfoFromSei
485     \brief Get SEI type, decode recovery point
486     \return 0: failure, 1: recovery, 2: unregistered user data, 3: both
487 */
488 enum {
489     ADM_H264_SEI_TYPE_OTHER = 0,
490     ADM_H264_SEI_TYPE_USER_DATA_UNREGISTERED = 1,
491     ADM_H264_SEI_TYPE_RECOVERY_POINT = 2
492 };
493 
getInfoFromSei(uint32_t nalSize,uint8_t * org,uint32_t * recoveryLength,uint32_t * unregistered)494 static int getInfoFromSei(uint32_t nalSize, uint8_t *org, uint32_t *recoveryLength, uint32_t *unregistered)
495 {
496     int originalNalSize=nalSize+16;
497     uint8_t *payloadBuffer=(uint8_t *)malloc(originalNalSize+AV_INPUT_BUFFER_PADDING_SIZE);
498     memset(payloadBuffer,0,originalNalSize+AV_INPUT_BUFFER_PADDING_SIZE);
499     uint8_t *payload=payloadBuffer;
500     int r=ADM_H264_SEI_TYPE_OTHER;
501     nalSize=ADM_unescapeH264(nalSize,org,payload);
502     if(nalSize>originalNalSize)
503     {
504         ADM_warning("NAL is way too big : %d, while we expected %d at most\n",nalSize,originalNalSize);
505         free(payloadBuffer);
506         return r;
507     }
508 
509     uint8_t *tail=payload+nalSize;
510 
511     while(payload+2<tail)
512     {
513         uint32_t sei_type=0,sei_size=0;
514         while(payload[0]==0xff)
515         {
516             sei_type+=0xff;payload++;
517             if(payload+2>=tail)
518             {
519                 seiprintf("Not enough data.\n");
520                 goto abtSei;
521             }
522         }
523         sei_type+=payload[0];payload++;
524         if(payload>=tail)
525         {
526             seiprintf("No data left after decoding SEI type.\n");
527             goto abtSei;
528         }
529         while(payload[0]==0xff)
530         {
531             sei_size+=0xff;payload++;
532             if(payload+1>=tail)
533             {
534                 seiprintf("Not enough data left after decoding SEI size.\n");
535                 goto abtSei;
536             }
537         }
538         sei_size+=payload[0];payload++;
539         seiprintf("Type: %u size: %u remaining: %d\n",sei_type,sei_size,tail-payload);
540         if(payload+sei_size>tail)
541         {
542             seiprintf("Not enough data.\n");
543             break;
544         }
545         switch(sei_type)
546         {
547             case 5: // Unregistered user data
548             {
549                 if(!unregistered) break;
550                 if(sei_size<16)
551                 {
552                     ADM_info("User data too short: %u\n",sei_size);
553                     break;
554                 }
555                 char *udata=(char *)malloc(16+sei_size+1);
556                 getBits bits(sei_size,payload);
557                 for(uint32_t i=0; i<sei_size; i++)
558                     udata[i]=bits.get(8);
559                 udata[sei_size]=0;
560                 int build;
561                 if(1!=sscanf(udata+16,"x264 - core %d",&build))
562                 {
563                     ADM_info("Unregistered user data doesn't match the one expected for x264\n");
564                     mixDump((uint8_t *)udata,sei_size);
565                     break;
566                 }
567                 free(udata);
568                 *unregistered=sei_size;
569                 ADM_info("Found unregistered user data from x264 build %d, size: %u\n",build,sei_size);
570                 r |= ADM_H264_SEI_TYPE_USER_DATA_UNREGISTERED;
571                 break;
572             }
573             case 6: // Recovery point
574             {
575                 if(!recoveryLength) break;
576                 getBits bits(sei_size,payload);
577                 int distance=bits.getUEG();
578                 if(distance<0)
579                 {
580                     ADM_warning("Invalid UE golomb code encountered while decoding recovery distance.\n");
581                     break;
582                 }
583                 seiprintf("Recovery distance: %d\n",distance);
584                 *recoveryLength=distance;
585                 r |= ADM_H264_SEI_TYPE_RECOVERY_POINT;
586                 break;
587             }
588             default:break;
589         }
590         payload+=sei_size;
591     }
592 abtSei:
593     free(payloadBuffer);
594     return r;
595 }
596 /**
597     \fn getNalType
598     \brief Return the slice type. The stream is escaped by the function. If recovery==0
599            or frame_num==0 I is considered IDR else as P.
600 */
getNalType(uint8_t * head,uint8_t * tail,uint32_t * flags,ADM_SPSInfo * sps,int * poc_lsb,int recovery)601 static bool getNalType (uint8_t *head, uint8_t *tail, uint32_t *flags, ADM_SPSInfo *sps, int *poc_lsb, int recovery)
602 {
603     if(tail<=head)
604         return false;
605     uint8_t *out=(uint8_t *)malloc(tail-head+AV_INPUT_BUFFER_PADDING_SIZE);
606     memset(out,0,tail-head+AV_INPUT_BUFFER_PADDING_SIZE);
607     int size=ADM_unescapeH264(tail-head,head,out);
608 
609     getBits bits(size,out);
610     uint32_t sliceType;
611     uint32_t fieldFlags=0;
612     int frame = -1;
613     *poc_lsb = -1;
614 
615     bits.getUEG();               // first mb in slice
616     sliceType = bits.getUEG31(); // get_ue_golomb_31??
617     if(sps && sps->log2MaxFrameNum > 3 && sps->log2MaxFrameNum < 17) // sanity check
618     {
619         bits.getUEG(); // skip PPS id
620         frame = bits.get(sps->log2MaxFrameNum);
621         if(!sps->frameMbsOnlyFlag && bits.get(1))
622         {
623             fieldFlags |= AVI_FIELD_STRUCTURE;
624             if(bits.get(1))
625                 fieldFlags |= AVI_BOTTOM_FIELD;
626             else
627                 fieldFlags |= AVI_TOP_FIELD;
628         }
629         if(sps->hasPocInfo)
630         {
631             if(*flags & AVI_IDR_FRAME) // from NAL
632                 bits.getUEG(); // skip idr_pic_id
633             *poc_lsb = bits.get(sps->log2MaxPocLsb);
634         }
635     }
636     if (sliceType > 9)
637     {
638       ADM_warning ("Weird Slice %d\n", sliceType);
639       free(out);
640       return false;
641     }
642     if (sliceType > 4)
643         sliceType -= 5;
644 
645     switch(sliceType)
646     {
647         case 3:
648         case 0: *flags = AVI_P_FRAME;break;
649         case 1: *flags = AVI_B_FRAME;break;
650         case 2: case 4:
651                 if((*flags & AVI_KEY_FRAME) && !sps)
652                     break; // trust NAL when we cannot verify
653                 if(!recovery || !frame)
654                     *flags = AVI_KEY_FRAME;
655                 else
656                     *flags = AVI_P_FRAME;
657                 if(!frame)
658                     *flags |= AVI_IDR_FRAME;
659                 break;
660 
661     }
662     *flags |= fieldFlags;
663     free(out);
664     return true;
665 }
666 
667 /**
668     \fn extractH264FrameType
669     \brief Parse access unit in buffer of size len, return frametype in flags (KEY/P/B).
670            nalSize should be either the NALU length size value retrieved from extradata or 0 for autodetect.
671            If ADM_SPSInfo is provided, return POC LSB or -1 if implicit or on error.
672            Return value: 1 on success, 0 on failure.
673            To be used only with AVCC (mkv/mp4) nal type (i.e. no startcode)
674 */
extractH264FrameType(uint8_t * buffer,uint32_t len,uint32_t nalSize,uint32_t * flags,int * pocLsb,ADM_SPSInfo * sps,uint32_t * extRecovery)675 uint8_t extractH264FrameType(uint8_t *buffer, uint32_t len, uint32_t nalSize, uint32_t *flags, int *pocLsb, ADM_SPSInfo *sps, uint32_t *extRecovery)
676 {
677     uint8_t *head = buffer, *tail = buffer + len;
678     uint8_t stream;
679     uint32_t i, length = 0;
680 
681     if(!nalSize || nalSize > 4)
682     { // Try to detect number of bytes used to code NAL length. Shaky.
683         nalSize = 4;
684         for(i = 0; i < nalSize; i++)
685         {
686             length = (length << 8) + head[i];
687             if(i && length > len)
688             {
689                 nalSize = i;
690                 break;
691             }
692         }
693     }
694     uint32_t recovery=0xff;
695     int p=-1;
696 
697     *flags=0;
698     while (head + nalSize < tail)
699     {
700         length = 0;
701         for(i = 0; i < nalSize; i++)
702             length = (length << 8) + head[i];
703         if (length > len)// || length < 2)
704         {
705             ADM_warning ("Warning , incomplete nal (%u/%u),(%0x/%0x)\n", length, len, length, len);
706             *flags = 0;
707             return 0;
708         }
709         head += nalSize;        // Skip nal lenth
710         len = (len > nalSize)? len - nalSize : 0;
711         int ref=(*(head)>>5) & 3;
712         stream = *(head) & 0x1F;
713 
714         switch (stream)
715         {
716             case NAL_SEI:
717                 {
718                     int sei=getInfoFromSei(length-1, head+1, &recovery, NULL);
719                     if(extRecovery)
720                     {
721                         if(sei & ADM_H264_SEI_TYPE_RECOVERY_POINT)
722                             *extRecovery=recovery;
723                         else
724                             recovery=*extRecovery;
725                     }
726                 }
727                 break;
728             case NAL_SPS:
729             case NAL_PPS:
730             case NAL_AU_DELIMITER:
731             case NAL_FILLER:
732                 break;
733             case NAL_IDR:
734                 *flags = AVI_KEY_FRAME + AVI_IDR_FRAME;
735                 if(!getNalType(head+1,head+length,flags,sps,&p,recovery))
736                     return 0;
737                 if(sps && !(*flags & AVI_IDR_FRAME))
738                 {
739                     ADM_warning("Mismatched frame (flags: %d) in IDR NAL unit!\n",*flags);
740                     *flags &= ~AVI_B_FRAME;
741                     *flags |= AVI_KEY_FRAME; // FIXME
742                 }
743                 if(pocLsb)
744                     *pocLsb=p;
745                 return 1;
746             case NAL_NON_IDR:
747                 if(!getNalType(head+1,head+length,flags,sps,&p,recovery))
748                     return 0;
749                 if(!ref && (*flags & AVI_B_FRAME))
750                     *flags |= AVI_NON_REF_FRAME;
751                 if(pocLsb)
752                     *pocLsb=p;
753                 return 1;
754             default:
755                 ADM_warning ("unknown nal ??0x%x\n", stream);
756                 break;
757         }
758         head+=length;
759         len = (len > length)? len - length : 0;
760     }
761     ADM_warning ("No stream\n");
762     return 0;
763 }
764 
765 /**
766       \fn extractH264FrameType_startCode
767       \brief return frametype in flags (KEY_FRAME or 0).
768       To be used only with  avi / mpeg TS nal type
769         (i.e. with startcode 00 00 00 01)
770 */
extractH264FrameType_startCode(uint8_t * buffer,uint32_t len,uint32_t * flags,int * pocLsb,ADM_SPSInfo * sps,uint32_t * extRecovery)771 uint8_t extractH264FrameType_startCode(uint8_t *buffer, uint32_t len, uint32_t *flags, int *pocLsb, ADM_SPSInfo *sps, uint32_t *extRecovery)
772 {
773     uint8_t *head = buffer, *tail = buffer + len;
774     uint8_t stream;
775     uint32_t hnt=0xffffffff;
776     uint32_t recovery=0xff;
777     int counter = 0, length = 0;
778     int ref = 0, p = -1;
779     bool last = false;
780 
781     *flags = 0;
782 
783     while (head + 2 < tail)
784     {
785         // Search startcode
786         hnt = (hnt << 8) + head[0];
787         if((hnt & 0xffffff) != 1)
788         {
789             head++;
790             if(head + 2 < tail)
791                 continue;
792             if(!counter) break;
793             last = true;
794             length = head - buffer + 2;
795         }
796         int prevNaluRefIdc = 0;
797         uint8_t prevNaluType = 0;
798         if(!last)
799         {
800             head++;
801             counter++;
802             if(counter > 1)
803                 length = head - buffer - 3; // 3 bytes start code length no matter zero-prefixed or not
804             prevNaluRefIdc = (*head >> 5) & 3;
805             prevNaluType = *(head++) & 0x1f;
806             if(!length)
807             {
808                 buffer = head;
809                 ref = prevNaluRefIdc;
810                 stream = prevNaluType;
811                 continue;
812             }
813         }
814         switch (stream)
815         {
816             case NAL_SEI:
817                 {
818                     int sei=getInfoFromSei(length, buffer, &recovery, NULL);
819                     if(extRecovery)
820                     {
821                         if(sei & ADM_H264_SEI_TYPE_RECOVERY_POINT)
822                             *extRecovery=recovery;
823                         else
824                             recovery=*extRecovery;
825                     }
826                 }
827                 break;
828             case NAL_SPS: case NAL_PPS: case NAL_FILLER: case NAL_AU_DELIMITER: break;
829             case NAL_IDR:
830                 *flags = AVI_KEY_FRAME + AVI_IDR_FRAME;
831                 if(!getNalType(buffer, buffer+length, flags, sps, &p, recovery))
832                     return 0;
833                 if(sps && !(*flags & AVI_IDR_FRAME))
834                 {
835                     ADM_warning("Mismatched frame (flags: %d) in IDR NAL unit!\n",*flags);
836                     *flags &= ~AVI_B_FRAME;
837                     *flags |= AVI_KEY_FRAME; // FIXME
838                 }
839                 if(pocLsb)
840                     *pocLsb=p;
841                 return 1;
842             case NAL_NON_IDR:
843                 if(!getNalType(buffer, buffer+length, flags, sps, &p, recovery))
844                     return 0;
845                 if(!ref && (*flags & AVI_B_FRAME))
846                     *flags |= AVI_NON_REF_FRAME;
847                 if(pocLsb)
848                     *pocLsb=p;
849                 return 1;
850             default:
851                 ADM_warning("Unknown NAL type ??0x%x\n", stream);
852                 break;
853         }
854         buffer = head;
855         ref = prevNaluRefIdc;
856         stream = prevNaluType;
857     }
858   printf ("No stream\n");
859   return 0;
860 }
861 
862 /**
863  *  \fn extractH264SEI
864  *  \brief If present, copy SEI containing x264 version info from access unit src to dest
865  */
extractH264SEI(uint8_t * src,uint32_t inlen,uint32_t nalSize,uint8_t * dest,uint32_t bufsize,uint32_t * outlen)866 bool extractH264SEI(uint8_t *src, uint32_t inlen, uint32_t nalSize, uint8_t *dest, uint32_t bufsize, uint32_t *outlen)
867 {
868     uint8_t *tail = src, *head = src + inlen;
869     uint8_t stream;
870     uint32_t i, length = 0;
871 
872     if(!nalSize || nalSize > 4)
873     { // Try to detect NAL length size.
874         nalSize = 4;
875         for(i = 0; i < nalSize; i++)
876         {
877             length = (length << 8) + tail[i];
878             if(i && length > inlen)
879             {
880                 nalSize = i;
881                 break;
882             }
883         }
884     }
885     uint32_t unregistered = 0;
886 
887     while(tail + nalSize < head)
888     {
889         length = 0;
890         for(i = 0; i < nalSize; i++)
891             length = (length << 8) + tail[i];
892         if(length > inlen)
893         {
894             ADM_warning ("Incomplete NALU, length: %u, available: %u\n", length, inlen);
895             return false;
896         }
897         tail += nalSize;
898         inlen = (inlen > nalSize)? inlen - nalSize : 0;
899         stream = *(tail) & 0x1f;
900 
901         if(stream == NAL_SEI)
902         {
903             if(getInfoFromSei(length-1,tail+1,NULL,&unregistered) & ADM_H264_SEI_TYPE_USER_DATA_UNREGISTERED)
904             {
905                 uint32_t l = nalSize + length;
906                 if(l > bufsize)
907                 {
908                     ADM_warning("Insufficient destination buffer, need %u, got %u\n",l,bufsize);
909                     return false;
910                 }
911                 if(dest)
912                     memcpy(dest,tail-nalSize,l); // what about emulation prevention bytes??
913                 if(outlen)
914                     *outlen = l;
915                 return true;
916             }
917         }
918         tail += length;
919         inlen = (inlen > length)? inlen - length : 0;
920     }
921 
922     return false;
923 }
924 
925 
926 
927 /**
928         \fn extractSPSInfo_mp4Header
929         \brief Only works for mp4 style headers i.e. begins by 0x01
930 */
extractSPSInfo_mp4Header(uint8_t * data,uint32_t len,ADM_SPSInfo * spsinfo)931 bool extractSPSInfo_mp4Header (uint8_t * data, uint32_t len, ADM_SPSInfo *spsinfo)
932 {
933     bool r=false;
934 
935     // duplicate
936     int myLen=len+AV_INPUT_BUFFER_PADDING_SIZE;
937     uint8_t *myData=new uint8_t[myLen];
938     memset(myData,0x2,myLen);
939     memcpy(myData,data,len);
940     myData[len]=0; // stop ff_h264_decode_extradata() from trying to parse the remaining buffer content as PPS
941 
942     // 1-Create parser
943     AVCodecParserContext *parser=av_parser_init(AV_CODEC_ID_H264);
944     AVCodecContext *ctx=NULL;
945     AVCodec *codec=NULL;
946     uint8_t *d=NULL;
947 
948     if(!parser)
949     {
950         ADM_error("cannot create h264 parser\n");
951         goto theEnd;
952     }
953     ADM_info("Parser created\n");
954     codec=avcodec_find_decoder(AV_CODEC_ID_H264);
955     if(!codec)
956     {
957         ADM_error("cannot create h264 codec\n");
958         goto theEnd;
959     }
960     ADM_info("Codec created\n");
961     ctx=avcodec_alloc_context3(codec);
962    if (avcodec_open2(ctx, codec, NULL) < 0)
963    {
964         ADM_error("cannot create h264 context\n");
965         goto theEnd;
966     }
967 
968     ADM_info("Context created, ticks_per_frame = %d\n",ctx->ticks_per_frame);
969     //2- Parse, let's add SPS prefix + Filler postfix to make life easier for libavcodec parser
970     ctx->extradata=myData;
971     ctx->extradata_size=len;
972      {
973          uint8_t *outptr=NULL;
974          int outsize=0;
975 
976          int used=av_parser_parse2(parser, ctx, &outptr, &outsize, d, 0, 0, 0,0);
977          printf("Used bytes %d/%d (+5)\n",used,len);
978          if(!used)
979          {
980            //ADM_warning("Failed to extract SPS info\n"); // it ain't necessarily so
981            //  goto theEnd;
982          }
983     }
984     // Size is not supposed to be set in AVCodecContext after parsing
985     //ADM_info("Width  : %d\n",ctx->width);
986     //ADM_info("Height : %d\n",ctx->height);
987     {
988         ffSpsInfo nfo;
989         if(!ff_h264_info(parser,ctx->ticks_per_frame,&nfo))
990         {
991             ADM_error("Cannot get sps info from lavcodec\n");
992             r=false;
993             goto theEnd;
994         }
995         ADM_info("Width2 : %d\n",nfo.width);
996         ADM_info("Height2: %d\n",nfo.height);
997         #define CPY(x) spsinfo->x=nfo.x
998         CPY(width);
999         CPY(height);
1000         CPY(fps1000);
1001         CPY(hasStructInfo);
1002         CPY(hasPocInfo);
1003         CPY(CpbDpbToSkip);
1004         CPY(log2MaxFrameNum);
1005         CPY(log2MaxPocLsb);
1006         CPY(frameMbsOnlyFlag);
1007         CPY(darNum);
1008         CPY(darDen);
1009         CPY(refFrames);
1010         r=true;
1011      }
1012     // cleanup
1013 theEnd:
1014     if(ctx)
1015     {
1016         avcodec_close(ctx);
1017 
1018         av_free(ctx);
1019     }
1020     if(parser)
1021         av_parser_close(parser);
1022 
1023     delete [] myData;
1024 
1025     return r;
1026 }
1027 
1028 /**
1029     \fn getRawH264SPS
1030     \brief Find the first SPS in mp4 style buffer and copy it to dest, return SPS length.
1031 */
getRawH264SPS(uint8_t * data,uint32_t len,uint32_t nalSize,uint8_t * dest,uint32_t maxsize)1032 uint32_t getRawH264SPS(uint8_t *data, uint32_t len, uint32_t nalSize, uint8_t *dest, uint32_t maxsize)
1033 {
1034     if(!dest || !maxsize)
1035         return 0;
1036 
1037     uint8_t *head=data, *tail=data+len;
1038     uint8_t stream;
1039 
1040     uint32_t i, length=0;
1041     if(!nalSize || nalSize > 4)
1042     { // Try to detect NAL length size.
1043         nalSize = 4;
1044         for(i = 0; i < nalSize; i++)
1045         {
1046             length = (length << 8) + head[i];
1047             if(i && length > len)
1048             {
1049                 nalSize = i;
1050                 break;
1051             }
1052         }
1053     }
1054 
1055     while(head + nalSize < tail)
1056     {
1057         length=0;
1058         for(i = 0; i < nalSize; i++)
1059             length = (length << 8) + head[i];
1060         if(length > len)
1061         {
1062             ADM_warning ("Incomplete NALU, length: %u, available: %u\n", length, len);
1063             return 0;
1064         }
1065         head += nalSize;
1066         len = (len>nalSize)? len-nalSize : 0;
1067         stream = *head & 0x1F;
1068 
1069         if(stream == NAL_SPS)
1070         {
1071             if(length>maxsize)
1072             {
1073                 ADM_warning("Buffer too small for SPS: need %u got %u\n",length,maxsize);
1074                 return 0;
1075             }
1076             memcpy(dest,head,length);
1077             return length;
1078         }
1079         head += length;
1080         len = (len>length)? len-length : 0;
1081     }
1082 
1083     return 0;
1084 }
1085 
1086 /**
1087     \fn getRawH264SPS_startCode
1088     \brief Find the first SPS in AnnexB style buffer and copy it to dest, return SPS length.
1089 */
getRawH264SPS_startCode(uint8_t * data,uint32_t len,uint8_t * dest,uint32_t maxsize)1090 uint32_t getRawH264SPS_startCode(uint8_t *data, uint32_t len, uint8_t *dest, uint32_t maxsize)
1091 {
1092     if(!dest || !maxsize)
1093         return 0;
1094 
1095     uint8_t *head = data;
1096     uint8_t *tail = head + len;
1097     uint8_t stream = 0;
1098     uint32_t hnt = 0xffffffff;
1099     int counter = 0, length = 0;
1100     bool last = false;
1101 #define MAX_NALU_TO_CHECK 4
1102     while(head + 2 < tail)
1103     {
1104         if(counter > MAX_NALU_TO_CHECK)
1105             return 0;
1106 
1107         hnt = (hnt << 8) + head[0];
1108         if((hnt & 0xffffff) != 1)
1109         {
1110             head++;
1111             if(head + 2 < tail)
1112                 continue;
1113             if(!counter) break;
1114             last = true;
1115         }
1116         length = head - data + 2;
1117         uint8_t prevNaluType = 0;
1118         if(!last)
1119         {
1120             head++;
1121             counter++;
1122             if(counter > 1)
1123                 length = head - data - 3; // likely one zerobyte too much, harmless
1124             prevNaluType = *head & 0x1f;
1125             if(!length)
1126             {
1127                 data = head;
1128                 stream = prevNaluType;
1129                 continue;
1130             }
1131         }
1132         if(stream == NAL_SPS)
1133         {
1134             if(length>maxsize)
1135             {
1136                 ADM_warning("Buffer too small for SPS: need %d, got %u\n",length,maxsize);
1137                 return 0;
1138             }
1139             memcpy(dest,data,length);
1140             return length;
1141         }
1142         data = head++;
1143         stream = prevNaluType;
1144     }
1145 #undef MAX_NALU_TO_CHECK
1146     return 0;
1147 }
1148 
1149 /**
1150     \fn extractSPSInfoFromData
1151     \brief Decode raw SPS data
1152 */
extractSPSInfoFromData(uint8_t * data,uint32_t length,ADM_SPSInfo * spsinfo)1153 bool extractSPSInfoFromData(uint8_t *data, uint32_t length, ADM_SPSInfo *spsinfo)
1154 {
1155     uint32_t myExtraLen=length+8;
1156     uint8_t *myExtra=new uint8_t[myExtraLen];
1157     memset(myExtra,0,myExtraLen);
1158     uint8_t *p=myExtra;
1159     // Create fake avcC extradata
1160     *p++=1;       // AVC version
1161     *p++=data[1]; // Profile
1162     *p++=data[2]; // Profile compatibility
1163     *p++=data[3]; // Level
1164     *p++=0xff;    // Nal size minus 1
1165     *p++=0xe1;    // 1x SPS
1166     *p++=length>>8;
1167     *p++=length&0xFF;
1168     memcpy(p,data,length);
1169 
1170     bool r = extractSPSInfo_mp4Header(myExtra,myExtraLen,spsinfo);
1171 
1172     delete [] myExtra;
1173     myExtra=NULL;
1174 
1175     return r;
1176 }
1177 
1178 /**
1179         \fn extractSPSInfo2
1180         \brief Same as extractSPSInfo, but using libavcodec
1181 */
extractSPSInfo_lavcodec(uint8_t * data,uint32_t len,ADM_SPSInfo * spsinfo)1182 uint8_t extractSPSInfo_lavcodec (uint8_t * data, uint32_t len, ADM_SPSInfo *spsinfo)
1183 {
1184     if(data[0]==1) return extractSPSInfo_mp4Header(data,len,spsinfo);
1185 
1186     ADM_info("Incoming SPS info\n");
1187     mixDump(data,len);
1188 
1189     ADM_info("converted SPS info\n");
1190 
1191     uint32_t converted;
1192     uint8_t buffer[256];
1193     if(! ADM_SPSannexBToMP4(len,data,&converted,buffer))
1194     {
1195         ADM_warning("Cannot convert SPS\n");
1196         return false;
1197     }
1198     mixDump(buffer,converted);
1199     return    extractSPSInfo_mp4Header(buffer,converted,spsinfo) ;
1200 
1201 }
1202 
extractSPSInfo(uint8_t * data,uint32_t len,ADM_SPSInfo * spsinfo)1203 bool  extractSPSInfo (uint8_t * data, uint32_t len, ADM_SPSInfo *spsinfo)
1204 {
1205 #define DPY(x) ADM_info(#x":%d\n",(int)spsinfo->x);
1206 #if 1
1207 
1208         bool l=extractSPSInfo_lavcodec(data,len,spsinfo);
1209         if(l)
1210         {
1211             DPY(width);
1212             DPY(height);
1213             DPY(fps1000);
1214             DPY(hasStructInfo);
1215             DPY(hasPocInfo);
1216             DPY(CpbDpbToSkip);
1217             DPY(log2MaxFrameNum);
1218             DPY(log2MaxPocLsb);
1219             DPY(frameMbsOnlyFlag);
1220             DPY(darNum);
1221             DPY(darDen);
1222         }else
1223         {
1224             ADM_info("Failed\n.");
1225         }
1226         return l;
1227 
1228 #else
1229         bool i=extractSPSInfo_internal(data,len,spsinfo);
1230         DPY(width);
1231         DPY(height);
1232         DPY(fps1000);
1233         DPY(hasStructInfo);
1234         DPY(CpbDpbToSkip);
1235         DPY(darNum);
1236         DPY(darDen);
1237         return i;
1238 #endif
1239 }
1240 /**
1241     \fn    packNalu
1242     \brief convert mpeg type NALU into mp4 header type nalu
1243 */
packNalu(int idx,NALU_descriptor * nalus,uint32_t * len,uint8_t ** data)1244 static void packNalu(int idx,NALU_descriptor *nalus,uint32_t *len,uint8_t **data)
1245 {
1246     NALU_descriptor *n=nalus+idx;
1247     uint32_t size=n->size;
1248     uint8_t *p=new uint8_t[size+1];
1249     *data=p;
1250     p[0]=n->nalu;
1251     *len=1+ADM_unescapeH264(n->size, n->start,p+1);
1252 }
1253 /**
1254     \fn ADM_getH264SpsPpsFromExtraData
1255     \brief Returns a copy of PPS/SPS extracted from extrdata
1256 */
ADM_getH264SpsPpsFromExtraData(uint32_t extraLen,uint8_t * extra,uint32_t * spsLen,uint8_t ** spsData,uint32_t * ppsLen,uint8_t ** ppsData)1257 bool ADM_getH264SpsPpsFromExtraData(uint32_t extraLen,uint8_t *extra,
1258                                     uint32_t *spsLen,uint8_t **spsData,
1259                                     uint32_t *ppsLen,uint8_t **ppsData)
1260 {
1261 
1262             if(extraLen<7) // not mov/mp4 formatted...
1263             {
1264                 ADM_error("Wrong extra data for h264\n");
1265                 return false;
1266             }
1267             //
1268             if(extra[0]==1) // MP4-type extradata
1269             {
1270                 ADM_info("MP4 style PPS/SPS\n");
1271 
1272                 int nbSps=extra[5]&0x1f;
1273                 if(nbSps!=1)
1274                 {
1275                     ADM_error("More or less than 1 sps\n");
1276                     return false;
1277 
1278                 }
1279                 uint8_t *c=extra+6;
1280                 *spsLen= (c[0]<<8)+(c[1]);
1281                 *spsData=c+2;
1282                 c+=2+*spsLen;
1283                 int nbPps=c[0]&0x1f;
1284                 if(nbPps!=1)
1285                 {
1286                     ADM_error("More or less than 1 pps\n");
1287                     return false;
1288                 }
1289                 c++;
1290                 *ppsLen= (c[0]<<8)+(c[1]);
1291                 *ppsData=c+2;
1292                 // Duplicate
1293                 uint8_t *y=new uint8_t [*spsLen];
1294                 memcpy(y,*spsData,*spsLen);
1295                 *spsData=y;
1296                 y=new uint8_t [*ppsLen];
1297                 memcpy(y,*ppsData,*ppsLen);
1298                 *ppsData=y;
1299                 ADM_info("Got extradata, ppslen=%d, spslen=%d\n",(int)(*ppsLen),(int)*spsLen);
1300                 return true;
1301 
1302             }else
1303             if(!extra[0] && !extra[1])
1304                 if(extra[2]==1 || (!extra[2] && extra[3]==1)) // 00 00 01 type extradata
1305             {
1306                 ADM_info("Startcoded PPS/SPS\n");
1307                 #define NALU_COUNT 10
1308                 NALU_descriptor nalus[NALU_COUNT];
1309                 int nbNalus=ADM_splitNalu(extra, extraLen+extra, NALU_COUNT,nalus);
1310                 //int ADM_findNalu(uint32_t nalu,uint32_t maxNalu,NALU_descriptor *desc);
1311                 if(nbNalus<2)
1312                 {
1313                     ADM_error("Not enough nalus in extradata (%s)\n",nbNalus);
1314                     return false;
1315                 }
1316                 int spsIndex=ADM_findNalu(NAL_SPS,nbNalus,nalus);
1317                 int ppsIndex=ADM_findNalu(NAL_PPS,nbNalus,nalus);
1318                 if(-1==spsIndex || -1 == ppsIndex)
1319                 {
1320                     ADM_error("Cant find sps/pps in nalus\n");
1321                     return false;
1322                 }
1323                 packNalu(spsIndex,nalus,spsLen,spsData);
1324                 packNalu(ppsIndex,nalus,ppsLen,ppsData);
1325                 return true;
1326             }
1327     return false;
1328 }
1329 /**
1330     \fn ADM_splitNalu
1331     \brief split a nalu annexb size into a list of nalu descriptor
1332 */
ADM_splitNalu(uint8_t * start,uint8_t * end,uint32_t maxNalu,NALU_descriptor * desc)1333 int ADM_splitNalu(uint8_t *start, uint8_t *end, uint32_t maxNalu,NALU_descriptor *desc)
1334 {
1335     bool first=true;
1336     uint8_t *head=start;
1337     uint32_t offset;
1338     uint8_t startCode,oldStartCode=0xff;
1339     bool zeroBytePrefixed,oldZbp=false;
1340     const uint32_t startCodePrefixLen=4;
1341     int index=0;
1342 
1343     while(true==ADM_findAnnexBStartCode(head,end,&startCode,&offset,&zeroBytePrefixed))
1344     {
1345         if(true==first)
1346         {
1347             head+=offset;
1348             first=false;
1349             oldStartCode=startCode;
1350             oldZbp=zeroBytePrefixed;
1351             continue;
1352         }
1353         if(index>=maxNalu)
1354         {
1355             ADM_warning("Number of NALUs exceeds max (%d), dropping the leftover.\n",maxNalu);
1356             return index;
1357         }
1358         desc[index].start=head;
1359         desc[index].size=offset-zeroBytePrefixed-startCodePrefixLen;
1360         desc[index].nalu=oldStartCode;
1361         desc[index].zerobyte=oldZbp;
1362         index++;
1363         head+=offset;
1364         oldStartCode=startCode;
1365         oldZbp=zeroBytePrefixed;
1366     }
1367     // leftover
1368     desc[index].start=head;
1369     desc[index].size=(uint32_t)(end-head);
1370     desc[index].nalu=oldStartCode;
1371     desc[index].zerobyte=oldZbp;
1372     index++;
1373     return index;
1374 }
1375 /**
1376     \fn ADM_findNalu
1377     \brief lookup for a specific NALU in the given buffer
1378 */
ADM_findNalu(uint32_t nalu,uint32_t maxNalu,NALU_descriptor * desc)1379 int ADM_findNalu(uint32_t nalu,uint32_t maxNalu,NALU_descriptor *desc)
1380 {
1381     for(int i=0;i<maxNalu;i++)
1382     {
1383             if((desc[i].nalu&0x1f) == (nalu&0x1f))
1384                 return i;
1385     }
1386     return -1;
1387 }
writeBE32(uint8_t * p,uint32_t size)1388 static void writeBE32(uint8_t *p, uint32_t size)
1389 {
1390     p[0]=size>>24;
1391     p[1]=(size>>16)&0xff;
1392     p[2]=(size>>8)&0xff;
1393     p[3]=(size>>0)&0xff;
1394 }
1395 /**
1396     \fn ADM_convertFromAnnexBToMP4_internal
1397     \brief convert annexB startcode (00 00 00 0 xx) to NALU
1398 */
ADM_convertFromAnnexBToMP4(uint8_t * inData,uint32_t inSize,uint8_t * outData,uint32_t outMaxSize)1399 int ADM_convertFromAnnexBToMP4(uint8_t *inData, uint32_t inSize,
1400                                uint8_t *outData,uint32_t outMaxSize)
1401 {
1402     uint8_t *tgt=outData;
1403     NALU_descriptor desc[MAX_NALU_PER_CHUNK+1];
1404     int nbNalu=ADM_splitNalu(inData,inData+inSize,MAX_NALU_PER_CHUNK,desc);
1405     const int nalHeaderSize=4;
1406     int outputSize=0;
1407 
1408 
1409     for(int i=0;i<nbNalu;i++)
1410     {
1411         NALU_descriptor *d=desc+i;
1412         aprintf("%d/%d : Nalu :0x%x size=%d\n",i,nbNalu,d->nalu,d->size);
1413         switch(d->nalu&0x1f)
1414         {
1415             case NAL_FILLER: break;
1416             case NAL_AU_DELIMITER: break;
1417             default:
1418                   writeBE32(tgt,1+d->size);
1419                   tgt[nalHeaderSize]=d->nalu;
1420                   memcpy(tgt+1+nalHeaderSize,d->start,d->size);
1421                   tgt+=d->size+1+nalHeaderSize;
1422                   break;
1423         }
1424         outputSize=tgt-outData;
1425         ADM_assert(outputSize<outMaxSize);
1426     }
1427     return outputSize;
1428 }
1429 //EOF
1430