a77bbb8746ceed6e9fe571928bd4f56ba5c4bd1d
1 /*
2 * Copyright (c) 2011, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
38 #include "demux.h"
39 #include "util.h"
41 char mpeg4head[45] = {0,0,0,0};
42 int get_esds_offset(const char *filename, struct demux *demux);
44 static AVFormatContext *
45 open_file(const char *filename)
46 {
47 static AVFormatContext *afc = NULL;
48 int err = avformat_open_input(&afc, filename, NULL, NULL);
50 if (!err)
51 err = avformat_find_stream_info(afc, NULL);
53 if (err < 0) {
54 ERROR("%s: lavf error %d", filename, err);
55 exit(1);
56 }
58 av_dump_format(afc, 0, filename, 0);
60 return afc;
61 }
63 static AVStream *
64 find_stream(AVFormatContext *afc)
65 {
66 AVStream *st = NULL;
67 unsigned int i;
69 for (i = 0; i < afc->nb_streams; i++) {
70 if (afc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st)
71 st = afc->streams[i];
72 else
73 afc->streams[i]->discard = AVDISCARD_ALL;
74 }
76 return st;
77 }
79 static struct demux * open_stream(const char * filename, int *width, int *height)
80 {
81 AVFormatContext *afc = open_file(filename);
82 AVStream *st = find_stream(afc);
83 AVCodecContext *cc = st->codec;
84 AVBitStreamFilterContext *bsf = NULL;
85 struct demux *demux;
87 if ((cc->codec_id != AV_CODEC_ID_H264) && (cc->codec_id != AV_CODEC_ID_MPEG2VIDEO) && ( cc->codec_id != AV_CODEC_ID_MPEG4)){
88 ERROR("could not open '%s': unsupported codec %d", filename, cc->codec_id);
89 return NULL;
90 }
92 if (cc->extradata && cc->extradata_size > 0 && cc->extradata[0] == 1) {
93 MSG("initializing bitstream filter");
94 bsf = av_bitstream_filter_init("h264_mp4toannexb");
95 if (!bsf) {
96 ERROR("could not open '%s': failed to initialize bitstream filter", filename);
97 return NULL;
98 }
99 }
101 *width = cc->width;
102 *height = cc->height;
104 demux = calloc(1, sizeof(*demux));
106 demux->afc = afc;
107 demux->cc = cc;
108 demux->st = st;
109 demux->bsf = bsf;
110 demux->first_in_buff = 0;
112 return demux;
113 }
115 struct demux * demux_init(const char * filename, int *width, int *height)
116 {
117 struct demux *demux;
119 av_register_all();
120 avcodec_register_all();
121 demux = open_stream(filename, width, height);
122 if ((demux != NULL) && (demux->cc->codec_id == AV_CODEC_ID_MPEG4)) {
123 if(get_esds_offset(filename, demux))
124 return NULL;
125 }
127 return demux;
128 }
130 int get_esds_offset(const char *filename, struct demux *demux) {
131 FILE *inputStream;
132 int i=0;
133 unsigned char *buffer = NULL;
134 unsigned long fileLen;
135 int esds_index=0;
136 inputStream = fopen(filename,"rb");
137 if (!inputStream) {
138 printf("Unable to open %s\n",filename);
139 return -1;
140 }
141 // Get the length
142 fseek(inputStream, 0, SEEK_END);
143 fileLen=ftell(inputStream);
144 fseek(inputStream, 0, SEEK_SET);
145 buffer=malloc(fileLen);
146 if (!buffer) {
147 printf("Memory error!\n");
148 fclose(inputStream);
149 return -1;
150 }
151 // File to buffer
152 fread(buffer, fileLen, 1, inputStream);
153 fclose(inputStream);
154 printf("Buffer starts: %p\n", &buffer[0]);
155 printf("Buffer ends: %p\n", &buffer[fileLen]);
156 //Determines offset of known_string
157 for(i=0; i<fileLen; i++) {
158 if((buffer[i] == 0x65) && (buffer[++i] == 0x73))
159 if((buffer[++i] == 0x64) && (buffer[i+1] == 0x73)) {
160 printf("data in buffer = %x %x %x %d \n",buffer[i],buffer[i+1],buffer[i+2],buffer[i+27]);
161 esds_index = i+27;
162 break;
163 }
164 }
165 demux->esds.length= buffer[esds_index];
166 demux->esds.data=malloc(demux->esds.length);
167 for(i=1; i<=demux->esds.length; i++) {
168 //printf(" index= %x \n",buffer[esds_index+i]);
169 demux->esds.data[i-1]=buffer[esds_index+i];
170 printf(" index= %x \n",demux->esds.data[i-1]);
171 }
172 free(buffer);
173 return 0;
174 }
178 int demux_read(struct demux *demux, char *input, int size)
179 {
180 AVPacket pk = {};
182 while (!av_read_frame(demux->afc, &pk)) {
183 if (pk.stream_index == demux->st->index) {
184 uint8_t *buf;
185 int bufsize;
187 if (demux->bsf) {
188 int ret;
189 ret = av_bitstream_filter_filter(demux->bsf, demux->cc,
190 NULL, &buf, &bufsize, pk.data, pk.size, 0);
191 if (ret < 0) {
192 ERROR("bsf error: %d", ret);
193 return 0;
194 }
195 } else {
196 buf = pk.data;
197 bufsize = pk.size;
198 }
200 if (bufsize > size)
201 bufsize = size;
203 if(demux->first_in_buff == 1) {
204 memcpy(input, demux->esds.data, demux->esds.length);
205 memcpy(input + demux->esds.length, buf, bufsize);
206 demux->first_in_buff =0;
207 bufsize = bufsize + demux->esds.length;
208 }
209 else {
210 memcpy(input, buf, bufsize);
211 }
213 if (demux->bsf)
214 av_free(buf);
216 av_free_packet(&pk);
218 return bufsize;
219 }
220 av_free_packet(&pk);
221 }
223 return 0;
224 }
226 int demux_rewind(struct demux *demux)
227 {
228 return av_seek_frame(demux->afc, demux->st->index, 0, AVSEEK_FLAG_FRAME);
229 }
231 void demux_deinit(struct demux *demux)
232 {
233 avformat_close_input(demux->afc);
234 if (demux->bsf)
235 av_bitstream_filter_close(demux->bsf);
236 free(demux->esds.data);
237 free(demux);
238 }