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 esds_length;
43 unsigned char *esds_data;
44 extern int first_in_buff;
45 int get_esds_offset(const char *filename);
49 static AVFormatContext *
50 open_file(const char *filename)
51 {
52 AVFormatContext *afc;
53 int err = av_open_input_file(&afc, filename, NULL, 0, NULL);
55 if (!err)
56 err = av_find_stream_info(afc);
58 if (err < 0) {
59 ERROR("%s: lavf error %d", filename, err);
60 exit(1);
61 }
63 dump_format(afc, 0, filename, 0);
65 return afc;
66 }
68 static AVStream *
69 find_stream(AVFormatContext *afc)
70 {
71 AVStream *st = NULL;
72 unsigned int i;
74 for (i = 0; i < afc->nb_streams; i++) {
75 if (afc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st)
76 st = afc->streams[i];
77 else
78 afc->streams[i]->discard = AVDISCARD_ALL;
79 }
81 return st;
82 }
84 static struct demux * open_stream(const char * filename, int *width, int *height)
85 {
86 AVFormatContext *afc = open_file(filename);
87 AVStream *st = find_stream(afc);
88 AVCodecContext *cc = st->codec;
89 AVBitStreamFilterContext *bsf = NULL;
90 struct demux *demux;
92 if ((cc->codec_id != CODEC_ID_H264) && (cc->codec_id != CODEC_ID_MPEG2VIDEO) && ( cc->codec_id != CODEC_ID_MPEG4)){
93 ERROR("could not open '%s': unsupported codec %d", filename, cc->codec_id);
94 return NULL;
95 }
97 if (cc->extradata && cc->extradata_size > 0 && cc->extradata[0] == 1) {
98 MSG("initializing bitstream filter");
99 bsf = av_bitstream_filter_init("h264_mp4toannexb");
100 if (!bsf) {
101 ERROR("could not open '%s': failed to initialize bitstream filter", filename);
102 return NULL;
103 }
104 }
106 *width = cc->width;
107 *height = cc->height;
109 demux = calloc(1, sizeof(*demux));
111 demux->afc = afc;
112 demux->cc = cc;
113 demux->st = st;
114 demux->bsf = bsf;
116 return demux;
117 }
119 struct demux * demux_init(const char * filename, int *width, int *height)
120 {
121 av_register_all();
122 avcodec_register_all();
123 if(get_esds_offset(filename))
124 return NULL;
125 return open_stream(filename, width, height);
126 }
128 int get_esds_offset(const char *filename) {
129 FILE *inputStream;
130 int i=0;
131 unsigned char *buffer = NULL;
132 unsigned long fileLen;
133 int esds_index=0;
134 inputStream = fopen(filename,"rb");
135 if (!inputStream) {
136 printf("Unable to open %s\n",filename);
137 return -1;
138 }
139 // Get the length
140 fseek(inputStream, 0, SEEK_END);
141 fileLen=ftell(inputStream);
142 fseek(inputStream, 0, SEEK_SET);
143 buffer=malloc(fileLen);
144 if (!buffer) {
145 printf("Memory error!\n");
146 fclose(inputStream);
147 return -1;
148 }
149 // File to buffer
150 fread(buffer, fileLen, 1, inputStream);
151 fclose(inputStream);
152 printf("Buffer starts: %p\n", &buffer[0]);
153 printf("Buffer ends: %p\n", &buffer[fileLen]);
154 //Determines offset of known_string
155 for(i=0; i<fileLen; i++) {
156 if((buffer[i] == 0x65) && (buffer[++i] == 0x73))
157 if((buffer[++i] == 0x64) && (buffer[i+1] == 0x73)) {
158 printf("data in buffer = %x %x %x %d \n",buffer[i],buffer[i+1],buffer[i+2],buffer[i+27]);
159 esds_index = i+27;
160 break;
161 }
162 }
163 esds_length= buffer[esds_index];
164 esds_data=malloc(esds_length);
165 for(i=1; i<=esds_length; i++) {
166 //printf(" index= %x \n",buffer[esds_index+i]);
167 esds_data[i-1]=buffer[esds_index+i];
168 printf(" index= %x \n",esds_data[i-1]);
169 }
170 free(buffer);
171 return 0;
172 }
176 int demux_read(struct demux *demux, char *input, int size)
177 {
178 AVPacket pk = {};
180 while (!av_read_frame(demux->afc, &pk)) {
181 if (pk.stream_index == demux->st->index) {
182 uint8_t *buf;
183 int bufsize;
185 if (demux->bsf) {
186 int ret;
187 ret = av_bitstream_filter_filter(demux->bsf, demux->cc,
188 NULL, &buf, &bufsize, pk.data, pk.size, 0);
189 if (ret < 0) {
190 ERROR("bsf error: %d", ret);
191 return 0;
192 }
193 } else {
194 buf = pk.data;
195 bufsize = pk.size;
196 }
198 if (bufsize > size)
199 bufsize = size;
201 if(first_in_buff == 1) {
202 memcpy(input,esds_data,esds_length);
203 memcpy(input+esds_length, buf, bufsize);
204 first_in_buff =0;
205 bufsize = bufsize+esds_length;
206 }
207 else {
208 memcpy(input, buf, bufsize);
209 }
211 if (demux->bsf)
212 av_free(buf);
214 av_free_packet(&pk);
216 return bufsize;
217 }
218 av_free_packet(&pk);
219 }
221 return 0;
222 }
224 int demux_rewind(struct demux *demux)
225 {
226 return av_seek_frame(demux->afc, demux->st->index, 0, AVSEEK_FLAG_FRAME);
227 }
229 void demux_deinit(struct demux *demux)
230 {
231 av_close_input_file(demux->afc);
232 if (demux->bsf)
233 av_bitstream_filter_close(demux->bsf);
234 free(esds_data);
235 free(demux);
236 }