1 /*
2 * Copyright (c) 2018 Texas Instruments, Inc.
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 #include "demux.h"
35 char mpeg4head[45] = { 0, 0, 0, 0 };
36 int get_esds_offset(const char *filename, struct demux *demux);
38 static AVFormatContext *
39 open_file(const char *filename)
40 {
41 AVFormatContext *afc = NULL;
42 int err = avformat_open_input(&afc, filename, NULL, NULL);
44 if (!err)
45 err = avformat_find_stream_info(afc, NULL);
47 if (err < 0) {
48 printf("%s: lavf error %d", filename, err);
49 exit(1);
50 }
52 av_dump_format(afc, 0, filename, 0);
54 return afc;
55 }
57 static AVStream *
58 find_stream(AVFormatContext *afc)
59 {
60 AVStream *st = NULL;
61 unsigned int i;
63 for (i = 0; i < afc->nb_streams; i++) {
64 if (afc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st)
65 st = afc->streams[i];
66 else
67 afc->streams[i]->discard = AVDISCARD_ALL;
68 }
70 return st;
71 }
73 static struct demux * open_stream(const char * filename, int *width,
74 int *height, int *bitdepth, enum AVPixelFormat *pix_fmt, enum AVCodecID *codec)
75 {
76 AVFormatContext *afc = open_file(filename);
77 AVStream *st = find_stream(afc);
78 AVCodecContext *cc = st->codec;
79 AVBitStreamFilterContext *bsf = NULL;
80 struct demux *demux;
82 if ((cc->codec_id != AV_CODEC_ID_H264) &&
83 (cc->codec_id != AV_CODEC_ID_MPEG2VIDEO) &&
84 (cc->codec_id != AV_CODEC_ID_MPEG4) &&
85 (cc->codec_id != AV_CODEC_ID_HEVC) &&
86 (cc->codec_id != AV_CODEC_ID_MJPEG)) {
87 printf("could not open '%s': unsupported codec %d", filename,
88 cc->codec_id);
89 return NULL;
90 }
92 if (cc->extradata && cc->extradata_size > 0 && cc->extradata[0] == 1) {
93 printf("initializing bitstream filter");
94 bsf = av_bitstream_filter_init("h264_mp4toannexb");
95 if (!bsf) {
96 printf("could not open '%s': failed to initialize bitstream filter",
97 filename);
98 return NULL;
99 }
100 }
102 *width = cc->width;
103 *height = cc->height;
104 *bitdepth = cc->bits_per_raw_sample;
105 *pix_fmt = cc->pix_fmt;
106 *codec = cc->codec_id;
108 demux = calloc(1, sizeof(*demux));
110 demux->afc = afc;
111 demux->cc = cc;
112 demux->st = st;
113 demux->bsf = bsf;
114 demux->first_in_buff = 0;
116 return demux;
117 }
119 struct demux * demux_init(const char * filename, int *width, int *height,
120 int *bitdepth, enum AVPixelFormat *pix_fmt, enum AVCodecID *codec)
121 {
122 struct demux *demux;
124 av_register_all();
125 avcodec_register_all();
126 demux = open_stream(filename, width, height, bitdepth, pix_fmt, codec);
127 if ((demux != NULL) && (demux->cc->codec_id == AV_CODEC_ID_MPEG4)) {
128 if (get_esds_offset(filename, demux))
129 return NULL;
130 }
132 return demux;
133 }
135 int get_esds_offset(const char *filename, struct demux *demux)
136 {
137 FILE *inputStream;
138 int i = 0;
139 unsigned char *buffer = NULL;
140 unsigned long fileLen;
141 int esds_index = 0;
142 inputStream = fopen(filename, "rb");
143 if (!inputStream) {
144 printf("Unable to open %s\n", filename);
145 return -1;
146 }
148 // Get the length
149 fseek(inputStream, 0, SEEK_END);
150 fileLen = ftell(inputStream);
151 fseek(inputStream, 0, SEEK_SET);
152 buffer = malloc(fileLen);
153 if (!buffer) {
154 printf("Memory error!\n");
155 fclose(inputStream);
156 return -1;
157 }
159 // File to buffer
160 fread(buffer, fileLen, 1, inputStream);
161 fclose(inputStream);
162 printf("Buffer starts: %p\n", &buffer[0]);
163 printf("Buffer ends: %p\n", &buffer[fileLen]);
165 //Determines offset of known_string
166 for (i = 0; i < fileLen; i++) {
167 if ((buffer[i] == 0x65) && (buffer[++i] == 0x73))
168 if ((buffer[++i] == 0x64) && (buffer[i + 1] == 0x73)) {
169 printf("data in buffer = %x %x %x %d \n",
170 buffer[i],
171 buffer[i + 1],
172 buffer[i + 2],
173 buffer[i + 27]);
174 esds_index = i + 27;
175 break;
176 }
177 }
179 demux->esds.length = buffer[esds_index];
180 demux->esds.data = malloc(demux->esds.length);
181 for (i = 1; i <= demux->esds.length; i++) {
182 demux->esds.data[i - 1] = buffer[esds_index + i];
183 printf(" index= %x \n", demux->esds.data[i - 1]);
184 }
186 free(buffer);
188 return 0;
189 }
191 int demux_read(struct demux *demux, unsigned char *input, int size)
192 {
193 AVPacket pk = { };
195 while (!av_read_frame(demux->afc, &pk)) {
196 if (pk.stream_index == demux->st->index) {
197 uint8_t *buf;
198 int bufsize;
200 if (demux->bsf) {
201 int ret;
202 ret = av_bitstream_filter_filter(demux->bsf,
203 demux->cc,
204 NULL,
205 &buf,
206 &bufsize,
207 pk.data,
208 pk.size,
209 0);
210 if (ret < 0) {
211 printf("bsf error: %d", ret);
212 return 0;
213 }
214 } else {
215 buf = pk.data;
216 bufsize = pk.size;
217 }
219 if (bufsize > size)
220 bufsize = size;
222 if (demux->first_in_buff == 1) {
223 memcpy(input, demux->esds.data, demux->esds.length);
224 memcpy(input + demux->esds.length, buf, bufsize);
225 demux->first_in_buff = 0;
226 bufsize = bufsize + demux->esds.length;
227 }
228 else {
229 memcpy(input, buf, bufsize);
230 }
232 if (demux->bsf)
233 av_free(buf);
235 av_free_packet(&pk);
237 return bufsize;
238 }
239 av_free_packet(&pk);
240 }
242 return 0;
243 }
245 int demux_rewind(struct demux *demux)
246 {
247 return av_seek_frame(demux->afc, demux->st->index, 0, AVSEEK_FLAG_FRAME);
248 }
250 void demux_deinit(struct demux *demux)
251 {
252 avformat_close_input(&demux->afc);
253 if (demux->bsf)
254 av_bitstream_filter_close(demux->bsf);
255 free(demux->esds.data);
256 free(demux);
257 }