source: branches/perian-1.1/bitstream_info.c @ 887

Revision 887, 23.3 KB checked in by astrange, 6 years ago (diff)

Merge trunk to 1.1 branch.

Line 
1/*
2 *  bitstream_info.c
3 *  Perian
4 *
5 *  Created by Graham Booker on 1/6/07.
6 *  Copyright 2007 Graham Booker. All rights reserved.
7 *
8 */
9
10#include "bitstream_info.h"
11
12#include <AudioToolbox/AudioToolbox.h>
13#include <QuickTime/QuickTime.h>
14
15#import "ac3tab.h"
16//ffmpeg's struct Picture conflicts with QuickDraw's
17#define Picture MPEGPICTURE
18
19#include "avcodec.h"
20
21#ifdef __BIG_ENDIAN__
22#define WORDS_BIGENDIAN
23#endif
24
25#include "bswap.h"
26#include "mpegvideo.h"
27#include "parser.h"
28#include "golomb.h"
29
30#include "CodecIDs.h"
31
32int inline MININT(int a, int b)
33{
34        return a < b ? a : b;
35}
36
37static const int nfchans_tbl[8] = { 2, 1, 2, 3, 3, 4, 4, 5 };
38static const int ac3_layout_no_lfe[8] = {
39        kAudioChannelLayoutTag_Stereo,
40        kAudioChannelLayoutTag_Mono,
41        kAudioChannelLayoutTag_Stereo,
42        kAudioChannelLayoutTag_ITU_3_0,
43        kAudioChannelLayoutTag_ITU_2_1,
44        kAudioChannelLayoutTag_ITU_3_1,
45        kAudioChannelLayoutTag_ITU_2_2,
46        kAudioChannelLayoutTag_ITU_3_2};
47
48static const int ac3_layout_lfe[8] = {
49        kAudioChannelLayoutTag_DVD_4,
50        kAudioChannelLayoutTag_Mono,  //No layout for this, hopefully we never have it
51        kAudioChannelLayoutTag_DVD_4,
52        kAudioChannelLayoutTag_DVD_10,
53        kAudioChannelLayoutTag_DVD_5,
54        kAudioChannelLayoutTag_DVD_11,
55        kAudioChannelLayoutTag_DVD_6,
56        kAudioChannelLayoutTag_ITU_3_2_1};
57
58static const uint16_t ac3_freqs[3] = { 48000, 44100, 32000 };
59static const uint16_t ac3_bitratetab[] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 448, 512, 576, 640};
60static const uint8_t ac3_halfrate[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3};
61
62/* From: http://svn.mplayerhq.hu/ac3/ (LGPL)
63 * Synchronize to ac3 bitstream.
64 * This function searches for the syncword '0xb77'.
65 *
66 * @param buf Pointer to "probable" ac3 bitstream buffer
67 * @param buf_size Size of buffer
68 * @return Returns the position where syncword is found, -1 if no syncword is found
69 */
70static int ac3_synchronize(uint8_t *buf, int buf_size)
71{
72    int i;
73       
74    for (i = 0; i < buf_size - 1; i++)
75        if (buf[i] == 0x0b && buf[i + 1] == 0x77)
76            return i;
77       
78    return -1;
79}
80
81/* A lot of this was stolen from: http://svn.mplayerhq.hu/ac3/ (LGPL)
82 * Fill info from an ac3 stream
83 *
84 * @param asdb Pointer to the AudioStreamBasicDescription to fill
85 * @param acl Pointer to the AudioChannelLayout to fill
86 * @param buffer Pointer to the buffer data to scan
87 * @param buff_size Size of the buffer
88 * @return 1 if successfull, 0 otherwise
89 */
90
91int parse_ac3_bitstream(AudioStreamBasicDescription *asbd, AudioChannelLayout *acl, uint8_t *buffer, int buff_size)
92{
93        int offset = ac3_synchronize(buffer, buff_size);
94        if(offset == -1)
95                return 0;
96       
97        if(buff_size < offset + 7)
98                return 0;
99       
100        uint8_t fscod_and_frmsizecod = buffer[offset + 4];
101       
102        uint8_t fscod = fscod_and_frmsizecod >> 6;
103        uint8_t frmsizecod = fscod_and_frmsizecod & 0x3f;
104        if(frmsizecod >= 38)
105                return 0;
106       
107        uint8_t bsid = buffer[offset + 5] >> 3;
108        if(bsid >= 0x12)
109                return 0;
110       
111        uint8_t acmod = buffer[offset + 6] >> 5;
112        uint8_t shift = 4;
113        if(acmod & 0x01 && acmod != 0x01)
114                shift -= 2;
115        if(acmod & 0x04)
116                shift -= 2;
117        if(acmod == 0x02)
118                shift -= 2;
119        uint8_t lfe = (buffer[offset + 6] >> shift) & 0x01;
120       
121        /* This is a valid frame!!! */
122        uint16_t bitrate = ac3_bitratetab[frmsizecod >> 1];
123        uint8_t half = ac3_halfrate[bsid];
124        int sample_rate = ac3_freqs[fscod] >> half;
125        int framesize;
126        switch (fscod) {
127                case 0:
128                        framesize = 4 * bitrate;
129                        break;
130                case 1:
131                        framesize = (320 * bitrate / 147 + (frmsizecod & 1 ? 1 : 0)) * 2;
132                        break;
133                case 2:
134                        framesize = 6 * bitrate;
135                        break;
136                default:
137                        break;
138        }
139       
140        shift = 0;
141        if(bsid > 8)
142                shift = bsid - 8;
143       
144        /* Setup the AudioStreamBasicDescription and AudioChannelLayout */
145        memset(asbd, 0, sizeof(AudioStreamBasicDescription));
146        asbd->mSampleRate = sample_rate >> shift;
147        if(offset == 0 && buff_size == framesize)
148                asbd->mFormatID = kAudioFormatAC3;
149        else
150                asbd->mFormatID = kAudioFormatAC3MS;
151        asbd->mFramesPerPacket = 1;
152        asbd->mChannelsPerFrame = nfchans_tbl[acmod] + lfe;
153       
154        memset(acl, 0, sizeof(AudioChannelLayout));
155        if(lfe)
156                acl->mChannelLayoutTag = ac3_layout_lfe[acmod];
157        else
158                acl->mChannelLayoutTag = ac3_layout_no_lfe[acmod];
159       
160        return 1;
161}
162
163static int parse_mpeg4_extra(FFusionParserContext *parser, const uint8_t *buf, int buf_size)
164{
165        ParseContext1 *pc1 = (ParseContext1 *)parser->pc->priv_data;
166        pc1->pc.frame_start_found = 0;
167       
168        MpegEncContext *s = pc1->enc;
169        GetBitContext gb1, *gb = &gb1;
170       
171        s->avctx = parser->avctx;
172        s->current_picture_ptr = &s->current_picture;
173       
174        init_get_bits(gb, buf, 8 * buf_size);
175        ff_mpeg4_decode_picture_header(s, gb);
176        return 1;
177}
178
179/*
180 * Long story short, FFMpeg's parsers suck for our use.  This function parses an mpeg4 bitstream,
181 * and assumes that it is given at least a full frame of data.
182 * @param parser A FFusionParserContext structure containg all our info
183 * @param buf The buffer to parse
184 * @param buf_size Size of the input buffer
185 * @param out_buf_size The number of bytes present in the first frame of data
186 * @param type The frame Type: FF_*_TYPE
187 * @param pts The PTS of the frame
188 * @return 1 if a frame is found, 0 otherwise
189 */
190static int parse_mpeg4_stream(FFusionParserContext *parser, const uint8_t *buf, int buf_size, int *out_buf_size, int *type, int *skippable)
191{
192        ParseContext1 *pc1 = (ParseContext1 *)parser->pc->priv_data;
193        pc1->pc.frame_start_found = 0;
194       
195        int endOfFrame = ff_mpeg4_find_frame_end(&(pc1->pc), buf, buf_size);
196       
197        MpegEncContext *s = pc1->enc;
198        GetBitContext gb1, *gb = &gb1;
199       
200        s->avctx = parser->avctx;
201        s->current_picture_ptr = &s->current_picture;
202       
203        init_get_bits(gb, buf, 8 * buf_size);
204        if(ff_mpeg4_decode_picture_header(s, gb) != 0)
205                return 0;
206       
207        *type = s->pict_type;
208        *skippable = (*type == FF_B_TYPE);
209#if 0 /*this was an attempt to figure out the PTS information and detect an out of order P frame before we hit its B frame */
210        int64_t *lastPtsPtr = (int64_t *)parser->internalContext;
211        int64_t lastPts = *lastPtsPtr;
212        int64_t currentPts = s->current_picture.pts;
213       
214        switch(s->pict_type)
215        {
216                case FF_I_TYPE:
217                        *lastPtsPtr = currentPts;
218                        *precedesAPastFrame = 0;
219                        break;
220                case FF_P_TYPE:
221                        if(currentPts > lastPts + 1)
222                                *precedesAPastFrame = 1;
223                        else
224                                *precedesAPastFrame = 0;
225                        *lastPtsPtr = currentPts;
226                        break;
227                case FF_B_TYPE:
228                        *precedesAPastFrame = 0;
229                        break;
230                default:
231                        break;
232        }
233#endif
234       
235        if(endOfFrame == END_NOT_FOUND)
236                *out_buf_size = buf_size;
237        else
238                *out_buf_size = endOfFrame;
239        return 1;
240}
241
242extern AVCodecParser mpeg4video_parser;
243
244FFusionParser ffusionMpeg4VideoParser = {
245        &mpeg4video_parser,
246        sizeof(uint64_t),
247        NULL,
248        parse_mpeg4_extra,
249        parse_mpeg4_stream,
250};
251
252typedef struct H264ParserContext_s
253{
254        int is_avc;
255        int nal_length_size;
256        int prevPts;
257       
258        int poc_type;
259        int log2_max_frame_num;
260        int frame_mbs_only_flag;
261        int pic_order_present_flag;
262
263        int log2_max_poc_lsb;
264        int poc_msb;
265        int prev_poc_lsb;
266
267        int delta_pic_order_always_zero_flag;
268        int offset_for_non_ref_pic;
269        int num_ref_frames_in_pic_order_cnt_cycle;
270        int sum_of_offset_for_ref_frames;
271       
272        int chroma_format_idc;
273}H264ParserContext;
274
275static int decode_nal(const uint8_t *buf, int buf_size, uint8_t *out_buf, int *out_buf_size, int *type, int *nal_ref_idc)
276{
277        int i;
278        int outIndex = 0;
279        int numNulls = 0;
280       
281        for(i=1; i<buf_size; i++)
282        {
283                if(buf[i] == 0)
284                        numNulls++;
285                else if(numNulls == 2)
286                {
287                        numNulls = 0;
288                        if(buf[i] < 3)
289                        {
290                                /* end of nal */
291                                outIndex -= 2;
292                                break;
293                        }
294                        else if(buf[i] == 3)
295                                /* This is just a simple escape of 0x00 00 03 */
296                                continue;
297                }
298                out_buf[outIndex] = buf[i];
299                outIndex++;
300        }
301       
302        if(outIndex <= 0)
303                return 0;
304       
305        *type = buf[0] & 0x1f;
306        *nal_ref_idc = (buf[0] >> 5) & 0x03;
307        *out_buf_size = outIndex;
308        return 1;
309}
310
311static void skip_scaling_list(GetBitContext *gb, int size){
312        int i, next = 8, last = 8;
313       
314    if(get_bits1(gb)) /* matrix not written, we use the predicted one */
315                for(i=0;i<size;i++){
316                        if(next)
317                                next = (last + get_se_golomb(gb)) & 0xff;
318                        if(!i && !next){ /* matrix not written, we use the preset one */
319                                break;
320                        }
321                        last = next ? next : last;
322                }
323}
324
325static void skip_scaling_matrices(GetBitContext *gb){
326    if(get_bits1(gb)){
327        skip_scaling_list(gb, 16); // Intra, Y
328        skip_scaling_list(gb, 16); // Intra, Cr
329        skip_scaling_list(gb, 16); // Intra, Cb
330        skip_scaling_list(gb, 16); // Inter, Y
331        skip_scaling_list(gb, 16); // Inter, Cr
332        skip_scaling_list(gb, 16); // Inter, Cb
333                skip_scaling_list(gb, 64);  // Intra, Y
334                skip_scaling_list(gb, 64);  // Inter, Y
335        }
336}
337
338static void decode_sps(H264ParserContext *context, const uint8_t *buf, int buf_size)
339{
340        GetBitContext getbit, *gb = &getbit;
341        int profile_idc;
342       
343        init_get_bits(gb, buf, 8 * buf_size);
344    profile_idc= get_bits(gb, 8);
345    get_bits1(gb);              //constraint_set0_flag
346    get_bits1(gb);              //constraint_set1_flag
347    get_bits1(gb);              //constraint_set2_flag
348    get_bits1(gb);              //constraint_set3_flag
349    get_bits(gb, 4);    //reserved
350        get_bits(gb, 8);        //level_idc
351        get_ue_golomb(gb);      //seq_parameter_set_id
352        if(profile_idc >= 100)
353        {
354                context->chroma_format_idc = get_ue_golomb(gb);
355                //high profile
356                if(context->chroma_format_idc == 3)     //chroma_format_idc
357                        get_bits1(gb);                  //residual_color_transfrom_flag
358                get_ue_golomb(gb);                      //bit_depth_luma_minus8
359                get_ue_golomb(gb);                      //bit_depth_chroma_minus8
360                get_bits1(gb);                          //transform_bypass
361                skip_scaling_matrices(gb);
362        }
363        context->log2_max_frame_num = get_ue_golomb(gb) + 4;
364        context->poc_type = get_ue_golomb(gb);
365        if(context->poc_type == 0)
366                context->log2_max_poc_lsb = get_ue_golomb(gb) + 4;
367        else if(context->poc_type == 1)
368        {
369                int i;
370               
371                context->delta_pic_order_always_zero_flag = get_bits1(gb);
372                context->offset_for_non_ref_pic = get_se_golomb(gb);
373                get_se_golomb(gb);      //offset_for_top_to_bottom_field
374                context->num_ref_frames_in_pic_order_cnt_cycle = get_ue_golomb(gb);
375                context->sum_of_offset_for_ref_frames = 0;
376                for(i=0; i<context->num_ref_frames_in_pic_order_cnt_cycle; i++)
377                        context->sum_of_offset_for_ref_frames += get_se_golomb(gb); //offset_for_ref_frame[i]
378        }
379        get_ue_golomb(gb);      //num_ref_frames
380        get_bits1(gb);          //gaps_in_frame_num_value_allowed_flag
381        get_ue_golomb(gb);      //pic_width_in_mbs_minus1
382        get_ue_golomb(gb);      //pic_height_in_map_units_minus1
383        context->frame_mbs_only_flag = get_bits1(gb);
384}
385
386static void decode_pps(H264ParserContext *context, const uint8_t *buf, int buf_size)
387{
388        GetBitContext getbit, *gb = &getbit;
389       
390        init_get_bits(gb, buf, 8 * buf_size);
391        get_ue_golomb(gb); //pic_parameter_set_id
392        get_ue_golomb(gb); //seq_parameter_set_id
393        get_bits1(gb); //entropy_coding_mode_flag
394        context->pic_order_present_flag = get_bits1(gb);
395}
396
397static int inline decode_slice_header(H264ParserContext *context, const uint8_t *buf, int buf_size, int nal_ref_idc, int nal_type, int just_type, int *type, int *pts)
398{
399        GetBitContext getbit, *gb = &getbit;
400        int slice_type;
401        int field_pic_flag = 0;
402        int bottom_field_flag = 0;
403        int frame_number;
404//      static const uint8_t slice_type_map[5] = {FF_P_TYPE, FF_B_TYPE, FF_I_TYPE, FF_SP_TYPE, FF_SI_TYPE};
405        static const uint8_t slice_type_map[5] = {FF_P_TYPE, FF_P_TYPE, FF_I_TYPE, FF_SP_TYPE, FF_SI_TYPE};
406       
407        init_get_bits(gb, buf, 8 * buf_size);
408       
409        get_ue_golomb(gb);      //first_mb_in_slice
410        slice_type = get_ue_golomb(gb);
411        if(slice_type > 9)
412                return 0;
413       
414        if(slice_type > 4)
415                slice_type -= 5;
416       
417        *type = slice_type_map[slice_type];
418        if(just_type)
419                return 1;
420       
421        get_ue_golomb(gb); //pic_parameter_set_id
422        frame_number = get_bits(gb, context->log2_max_frame_num);
423        if(!context->frame_mbs_only_flag)
424        {
425                field_pic_flag = get_bits1(gb);
426                if(field_pic_flag)
427                {
428                        bottom_field_flag = get_bits1(gb);
429                }
430        }
431        if(nal_type == 5)
432                get_ue_golomb(gb);  //idr_pic_id
433        if(context->poc_type == 0)
434        {
435                int pts_lsb = get_bits(gb, context->log2_max_poc_lsb);
436                int delta_pic_order_cnt_bottom = 0;
437                int maxPicOrderCntLsb = 1 << context->log2_max_poc_lsb;
438                int pic_order_msb;
439               
440                if(context->pic_order_present_flag && !field_pic_flag)
441                        delta_pic_order_cnt_bottom = get_se_golomb(gb);
442                if((pts_lsb < context->prev_poc_lsb) && (context->prev_poc_lsb - pts_lsb) >= maxPicOrderCntLsb)
443                        pic_order_msb = context->poc_msb + maxPicOrderCntLsb;
444                else if((pts_lsb > context->prev_poc_lsb) && (pts_lsb - context->prev_poc_lsb) > maxPicOrderCntLsb)
445                        pic_order_msb = context->poc_msb - maxPicOrderCntLsb;
446                else
447                        pic_order_msb = context->poc_msb;
448               
449                context->poc_msb = pic_order_msb;
450               
451                *pts = pic_order_msb + pts_lsb;
452                if(delta_pic_order_cnt_bottom < 0)
453                        *pts += delta_pic_order_cnt_bottom;
454                       
455        }
456        else if(context->poc_type == 1 && !context->delta_pic_order_always_zero_flag)
457        {
458                int delta_pic_order_cnt[2] = {0, 0};
459                delta_pic_order_cnt[0] = get_se_golomb(gb);
460                if(context->pic_order_present_flag && !field_pic_flag)
461                        delta_pic_order_cnt[1] = get_se_golomb(gb);
462               
463                int frame_num_offset = 0;  //I think this is wrong, but the pts code isn't used anywhere, so no harm yet and this removes a warning.
464               
465                int abs_frame_num = 0;
466                int num_ref_frames_in_pic_order_cnt_cycle = context->num_ref_frames_in_pic_order_cnt_cycle;
467                if(num_ref_frames_in_pic_order_cnt_cycle != 0)
468                        abs_frame_num = frame_num_offset + frame_number;
469               
470                if(nal_ref_idc == 0 && abs_frame_num > 0)
471                        abs_frame_num--;
472               
473                int expected_delta_per_poc_cycle = context->sum_of_offset_for_ref_frames;
474                int expectedpoc = 0;
475                if(abs_frame_num > 0)
476                {
477                        int poc_cycle_cnt = (abs_frame_num - 1) / num_ref_frames_in_pic_order_cnt_cycle;
478                       
479                        expectedpoc = poc_cycle_cnt * expected_delta_per_poc_cycle + context->sum_of_offset_for_ref_frames;
480                }
481               
482                if(nal_ref_idc == 0)
483                        expectedpoc = expectedpoc + context->offset_for_non_ref_pic;
484                *pts = expectedpoc + delta_pic_order_cnt[0];
485        }
486       
487        return 1;
488}
489
490#define NAL_PEEK_SIZE 32
491
492static int inline decode_nals(H264ParserContext *context, const uint8_t *buf, int buf_size, int *type, int *skippable)
493{
494        int nalsize = 0;
495        int buf_index = 0;
496        int ret = 0;
497        int pts_decoded = 0;
498        int lowestType = 20;
499       
500        *skippable = 1;
501       
502#if 0 /*this was an attempt to figure out the PTS information and detect an out of order P frame before we hit its B frame */
503        if(context->poc_type == 2)
504        {
505                //decode and display order are the same
506                pts_decoded = 1;
507                *precedesAPastFrame = 0;
508        }
509#endif
510       
511        for(;;)
512        {
513                if(context->is_avc)
514                {
515                        if(buf_index >= buf_size)
516                                break;
517                        nalsize = 0;
518                        switch (context->nal_length_size) {
519                                case 1:
520                                        nalsize = buf[buf_index];
521                                        buf_index++;
522                                        break;
523                                case 2:
524                                        nalsize = (buf[buf_index] << 8) | buf[buf_index+1];
525                                        buf_index += 2;
526                                        break;
527                                case 3:
528                                        nalsize = (buf[buf_index] << 16) | (buf[buf_index+1] << 8) | buf[buf_index + 2];
529                                        buf_index += 3;
530                                        break;
531                                case 4:
532                                        nalsize = (buf[buf_index] << 24) | (buf[buf_index+1] << 16) | (buf[buf_index + 2] << 8) | buf[buf_index + 3];
533                                        buf_index += 4;
534                                        break;
535                                default:
536                                        break;
537                        }
538                        if(nalsize <= 1 || nalsize > buf_size)
539                        {
540                                if(nalsize == 1)
541                                {
542                                        buf_index++;
543                                        continue;
544                                }
545                                else
546                                        break;
547                        }
548                }
549                else
550                {
551                        int num_nuls = 0;
552                        int start_offset = 0;
553                        //do start code prefix search
554                        for(; buf_index < buf_size; buf_index++)
555                        {
556                                if(buf[buf_index] == 0)
557                                        num_nuls++;
558                                else
559                                {
560                                        if(num_nuls >= 2 && buf[buf_index] == 1)
561                                                break;
562                                        num_nuls = 0;
563                                }
564                        }
565                        start_offset = buf_index + 1;
566                        //do start code prefix search
567                        for(buf_index++; buf_index < buf_size; buf_index++)
568                        {
569                                if(buf[buf_index] == 0)
570                                {
571                                        if(num_nuls == 2)
572                                                break;
573                                        num_nuls++;
574                                }
575                                else
576                                {
577                                        if(num_nuls == 2 && buf[buf_index] == 1)
578                                                break;
579                                        num_nuls = 0;
580                                }
581                        }
582                        if(start_offset >= buf_size)
583                                //no more
584                                break;
585                        nalsize = buf_index - start_offset;
586                        if(buf_index < buf_size)
587                                //Take off the next NAL's startcode
588                                nalsize -= 2;
589                        //skip the start code
590                        buf_index = start_offset;
591                }
592
593                uint8_t partOfNal[NAL_PEEK_SIZE];
594                int decodedNalSize, nalType;
595                int nal_ref_idc;
596                int slice_type = 0;
597               
598                if(decode_nal(buf + buf_index, MININT(nalsize, NAL_PEEK_SIZE), partOfNal, &decodedNalSize, &nalType, &nal_ref_idc))
599                {
600                        int pts = 0;
601                        if(nalType == 1 || nalType == 2)
602                        {
603                                if(decode_slice_header(context, partOfNal, decodedNalSize, nal_ref_idc, nalType, pts_decoded, &slice_type, &pts))
604                                {
605                                        ret = 1;
606                                        if(slice_type < lowestType)
607                                                lowestType = slice_type;
608                                        if(nal_ref_idc)
609                                                *skippable = 0;
610                                        if(pts_decoded == 0)
611                                        {
612                                                pts_decoded = 1;
613                                                if(pts > context->prevPts)
614                                                {
615                                                        if(pts < context->prevPts)
616                                                                lowestType = FF_B_TYPE;
617                                                        context->prevPts = pts;
618                                                }
619                                        }
620                                }
621                               
622                                // Parser users assume I-frames are IDR-frames
623                                // but in H.264 they don't have to be.
624                                // Mark these as P-frames if they effectively are.
625                                if (lowestType == FF_I_TYPE) lowestType = FF_P_TYPE;
626                        }
627                        else if(nalType == 5)
628                        {
629                                ret = 1;
630#if 0 /*this was an attempt to figure out the PTS information and detect an out of order P frame before we hit its B frame */
631                                context->prev_poc_lsb = 0;
632                                context->poc_msb = 0;
633                                context->prevPts = 0;
634                                *precedesAPastFrame = 0;
635#endif
636                                *skippable = 0;
637                                lowestType = FF_I_TYPE;
638                        }
639                }
640                buf_index += nalsize;
641        }
642        if(lowestType != 20)
643                *type = lowestType;
644       
645        return ret;
646}
647
648/*
649 * This function parses an h.264 bitstream, and assumes that it is given at least a full frame of data.
650 * @param parser A FFusionParserContext structure containg all our info
651 * @param buf The buffer to parse
652 * @param buf_size Size of the input buffer
653 * @param out_buf_size The number of bytes present in the first frame of data
654 * @param type The frame Type: FF_*_TYPE
655 * @param pts The PTS of the frame
656 * @return 1 if a frame is found, 0 otherwise
657 */
658static int parse_h264_stream(FFusionParserContext *parser, const uint8_t *buf, int buf_size, int *out_buf_size, int *type, int *skippable)
659{
660        int endOfFrame;
661        int size = 0;
662        const uint8_t *parseBuf = buf;
663        int parseSize;
664
665        /*
666         * Somehow figure out of frame type
667         * For our use, a frame with any B slices is a B frame, and then a frame with any P slices is a P frame.
668         * An I frame has only I slices.
669         * I expect this involves a NAL decoder, and then look at the slice types.
670         * Nal is a f(1) always set to 0, u(2) of nal_ref_idc, and then u(5) of nal_unit_type.
671         * Nal types 1, 2 start a non-I frame, and type 5 starts an I frame.  Each start with a slice header.
672         * Slice header has a ue(v) for first_mb_in_slice and then a ue(v) for the slice_type
673         * Slice types 0, 5 are P, 1, 6 are B, 2, 7 are I
674         */
675       
676        do
677        {
678                parseBuf = parseBuf + size;
679                parseSize = buf_size - size;
680                endOfFrame = (parser->parserStructure->avparse->split)(parser->avctx, parseBuf, parseSize);
681                if(endOfFrame == 0)
682                        size = buf_size;
683                else
684                {
685                        size += endOfFrame;
686                        parseSize = endOfFrame;
687                }
688        }while(decode_nals(parser->internalContext, parseBuf, parseSize, type, skippable) == 0 && size < buf_size);
689               
690        *out_buf_size = size;
691        return 1;
692}
693
694static int init_h264_parser(FFusionParserContext *parser)
695{
696        H264ParserContext *context = parser->internalContext;
697       
698        context->nal_length_size = 2;
699        context->is_avc = 0;
700        return 1;
701}
702
703static int parse_extra_data_h264(FFusionParserContext *parser, const uint8_t *buf, int buf_size)
704{
705        H264ParserContext *context = parser->internalContext;
706        const uint8_t *cur = buf;
707        int count, i, type, ref;
708       
709        context->is_avc = 1;
710        count = *(cur+5) & 0x1f;
711        cur += 6;
712        for (i=0; i<count; i++)
713        {
714                int size = AV_RB16(cur);
715                int out_size = 0;
716                uint8_t *decoded = malloc(size);
717                if(decode_nal(cur + 2, size, decoded, &out_size, &type, &ref))
718                        decode_sps(context, decoded, out_size);
719                cur += size + 2;
720                free(decoded);
721        }
722        count = *(cur++);
723        for (i=0; i<count; i++)
724        {
725                int size = AV_RB16(cur);
726                int out_size = 0;
727                uint8_t *decoded = malloc(size);
728                if(decode_nal(cur + 2, size, decoded, &out_size, &type, &ref))
729                        decode_pps(context, decoded, out_size);
730                cur += size + 2;
731                free(decoded);
732        }
733       
734        context->nal_length_size = ((*(buf+4)) & 0x03) + 1;
735       
736        return 1;
737}
738
739extern AVCodecParser h264_parser;
740
741FFusionParser ffusionH264Parser = {
742        &h264_parser,
743        sizeof(H264ParserContext),
744        init_h264_parser,
745        parse_extra_data_h264,
746        parse_h264_stream,
747};
748
749FFusionParser *ffusionFirstParser = NULL;
750
751void registerFFusionParsers(FFusionParser *parser)
752{
753    parser->next = ffusionFirstParser;
754    ffusionFirstParser = parser;
755}
756
757void initFFusionParsers()
758{
759        static Boolean inited = FALSE;
760        if(inited == FALSE)
761        {
762                inited = TRUE;
763                registerFFusionParsers(&ffusionMpeg4VideoParser);
764                registerFFusionParsers(&ffusionH264Parser);
765        }
766}
767
768void freeFFusionParser(FFusionParserContext *parser)
769{
770        if(parser->pc)
771        {
772                if(parser->pc->priv_data)
773                        av_free(parser->pc->priv_data);
774                av_free(parser->pc);
775        }
776        if(parser->avctx)
777                av_free(parser->avctx);
778        if(parser->internalContext)
779                av_free(parser->internalContext);
780        free(parser);
781}
782
783FFusionParserContext *ffusionParserInit(int codec_id)
784{
785    AVCodecParserContext *s;
786    AVCodecParser *parser;
787        FFusionParser *ffParser;
788    int ret;
789        struct AVCodecContext *ctx = avcodec_alloc_context();
790       
791    if(codec_id == CODEC_ID_NONE)
792        return NULL;
793       
794        if (!ffusionFirstParser) initFFusionParsers();
795       
796    for(ffParser = ffusionFirstParser; ffParser != NULL; ffParser = ffParser->next) {
797                parser = ffParser->avparse;
798        if (parser->codec_ids[0] == codec_id ||
799            parser->codec_ids[1] == codec_id ||
800            parser->codec_ids[2] == codec_id ||
801            parser->codec_ids[3] == codec_id ||
802            parser->codec_ids[4] == codec_id)
803            goto found;
804    }
805    return NULL;
806found:
807        s = av_mallocz(sizeof(AVCodecParserContext));
808    if (!s)
809        return NULL;
810    s->parser = parser;
811    s->priv_data = av_mallocz(parser->priv_data_size);
812    if (!s->priv_data) {
813        av_free(s);
814        return NULL;
815    }
816    if (parser->parser_init) {
817        ret = parser->parser_init(s);
818        if (ret != 0) {
819            av_free(s->priv_data);
820            av_free(s);
821            return NULL;
822        }
823    }
824    s->fetch_timestamp=1;
825        s->flags |= PARSER_FLAG_COMPLETE_FRAMES;
826       
827        FFusionParserContext *parserContext = malloc(sizeof(FFusionParserContext));
828        parserContext->avctx = ctx;
829        parserContext->pc = s;
830        parserContext->parserStructure = ffParser;
831        if(ffParser->internalContextSize)
832                parserContext->internalContext = av_mallocz(ffParser->internalContextSize);
833        else
834                parserContext->internalContext = NULL;
835        if(ffParser->init)
836                (ffParser->init)(parserContext);
837    return parserContext;
838}
839
840/*
841 * @param parser FFusionParserContext pointer
842 * @param buf The buffer to parse
843 * @param buf_size Size of the input buffer
844 * @return 1 if successful, 0 otherwise
845 */
846 int ffusionParseExtraData(FFusionParserContext *parser, const uint8_t *buf, int buf_size)
847{
848         if(parser->parserStructure->extra_data)
849                 return (parser->parserStructure->extra_data)(parser, buf, buf_size);
850         return 1;       
851}
852
853/*
854 * @param parser FFusionParserContext pointer
855 * @param buf The buffer to parse
856 * @param buf_size Size of the input buffer
857 * @param out_buf_size The number of bytes present in the first frame of data
858 * @param type The frame Type: FF_*_TYPE
859 * @param pts The PTS of the frame
860 * @return 1 if a frame is found, 0 otherwise
861 */
862int ffusionParse(FFusionParserContext *parser, const uint8_t *buf, int buf_size, int *out_buf_size, int *type, int *skippable)
863{
864        if(parser->parserStructure->parser_parse)
865                return (parser->parserStructure->parser_parse)(parser, buf, buf_size, out_buf_size, type, skippable);
866        return 0;
867}
868
869int ffusionIsParsedVideoDecodable(FFusionParserContext *parser)
870{
871        if (!parser) return 1;
872       
873        if (parser->parserStructure == &ffusionH264Parser) {
874                H264ParserContext *h264parser = parser->internalContext;
875               
876                // don't try to decode interlaced or 4:2:2 H.264
877                return (h264parser->frame_mbs_only_flag == 1) && (h264parser->chroma_format_idc <= 1);
878        }
879       
880        return 1;
881}
Note: See TracBrowser for help on using the repository browser.