annotate h264_parser.c @ 7855:9a135b6a1dc7 libavcodec

Correct order of parsing for pulse scalefactor band and offset to match the specification. Patch by Alex Converse (alex converse gmail com)
author superdump
date Sat, 13 Sep 2008 18:47:43 +0000
parents 2b72f9bc4f06
children 38d577c3cb60
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4975
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
1 /*
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
2 * H.26L/H.264/AVC/JVT/14496-10/... parser
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
3 * Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
4 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
5 * This file is part of FFmpeg.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
6 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
11 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
15 * Lesser General Public License for more details.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
16 *
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
20 */
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
21
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
22 /**
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
23 * @file h264_parser.c
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
24 * H.264 / AVC / MPEG4 part10 parser.
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
25 * @author Michael Niedermayer <michaelni@gmx.at>
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
26 */
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
27
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
28 #include "parser.h"
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
29 #include "h264_parser.h"
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
30
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
31 #include <assert.h>
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
32
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
33
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
34 int ff_h264_find_frame_end(H264Context *h, const uint8_t *buf, int buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
35 {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
36 int i;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
37 uint32_t state;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
38 ParseContext *pc = &(h->s.parse_context);
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
39 //printf("first %02X%02X%02X%02X\n", buf[0], buf[1],buf[2],buf[3]);
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
40 // mb_addr= pc->mb_addr - 1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
41 state= pc->state;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
42 if(state>13)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
43 state= 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
44
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
45 for(i=0; i<buf_size; i++){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
46 if(state==7){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
47 for(; i<buf_size; i++){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
48 if(!buf[i]){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
49 state=2;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
50 break;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
51 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
52 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
53 }else if(state<=2){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
54 if(buf[i]==1) state^= 5; //2->7, 1->4, 0->5
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
55 else if(buf[i]) state = 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
56 else state>>=1; //2->1, 1->0, 0->0
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
57 }else if(state<=5){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
58 int v= buf[i] & 0x1F;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
59 if(v==7 || v==8 || v==9){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
60 if(pc->frame_start_found){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
61 i++;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
62 found:
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
63 pc->state=7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
64 pc->frame_start_found= 0;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
65 return i-(state&5);
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
66 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
67 }else if(v==1 || v==2 || v==5){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
68 if(pc->frame_start_found){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
69 state+=8;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
70 continue;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
71 }else
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
72 pc->frame_start_found = 1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
73 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
74 state= 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
75 }else{
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
76 if(buf[i] & 0x80)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
77 goto found;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
78 state= 7;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
79 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
80 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
81 pc->state= state;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
82 return END_NOT_FOUND;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
83 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
84
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
85 static int h264_parse(AVCodecParserContext *s,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
86 AVCodecContext *avctx,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
87 const uint8_t **poutbuf, int *poutbuf_size,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
88 const uint8_t *buf, int buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
89 {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
90 H264Context *h = s->priv_data;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
91 ParseContext *pc = &h->s.parse_context;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
92 int next;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
93
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
94 if(s->flags & PARSER_FLAG_COMPLETE_FRAMES){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
95 next= buf_size;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
96 }else{
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
97 next= ff_h264_find_frame_end(h, buf, buf_size);
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
98
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
99 if (ff_combine_frame(pc, next, &buf, &buf_size) < 0) {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
100 *poutbuf = NULL;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
101 *poutbuf_size = 0;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
102 return buf_size;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
103 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
104
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
105 if(next<0 && next != END_NOT_FOUND){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
106 assert(pc->last_index + next >= 0 );
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
107 ff_h264_find_frame_end(h, &pc->buffer[pc->last_index + next], -next); //update state
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
108 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
109 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
110
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
111 *poutbuf = buf;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
112 *poutbuf_size = buf_size;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
113 return next;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
114 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
115
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
116 static int h264_split(AVCodecContext *avctx,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
117 const uint8_t *buf, int buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
118 {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
119 int i;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
120 uint32_t state = -1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
121 int has_sps= 0;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
122
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
123 for(i=0; i<=buf_size; i++){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
124 if((state&0xFFFFFF1F) == 0x107)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
125 has_sps=1;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
126 /* if((state&0xFFFFFF1F) == 0x101 || (state&0xFFFFFF1F) == 0x102 || (state&0xFFFFFF1F) == 0x105){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
127 }*/
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
128 if((state&0xFFFFFF00) == 0x100 && (state&0xFFFFFF1F) != 0x107 && (state&0xFFFFFF1F) != 0x108 && (state&0xFFFFFF1F) != 0x109){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
129 if(has_sps){
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
130 while(i>4 && buf[i-5]==0) i--;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
131 return i-4;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
132 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
133 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
134 if (i<buf_size)
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
135 state= (state<<8) | buf[i];
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
136 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
137 return 0;
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
138 }
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
139
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
140
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
141 AVCodecParser h264_parser = {
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
142 { CODEC_ID_H264 },
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
143 sizeof(H264Context),
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
144 NULL,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
145 h264_parse,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
146 ff_parse_close,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
147 h264_split,
9a6a0818e93f split h264.c to move parser in its own file
aurel
parents:
diff changeset
148 };