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

Revision 719, 21.7 KB checked in by gbooker, 7 years ago (diff)

Removed redundant code

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