]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - jacinto7_multimedia/viddec-test-app.git/blob - demux.c
Add DRM compile flags
[jacinto7_multimedia/viddec-test-app.git] / demux.c
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;
119 struct demux * demux_init(const char * filename, int *width, int *height,
120                         int *bitdepth, enum AVPixelFormat *pix_fmt, enum AVCodecID *codec)
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;
135 int get_esds_offset(const char *filename, struct demux *demux)
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;
191 int demux_read(struct demux *demux, unsigned char *input, int size)
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;
245 int demux_rewind(struct demux *demux)
247         return av_seek_frame(demux->afc, demux->st->index, 0, AVSEEK_FLAG_FRAME);
250 void demux_deinit(struct demux *demux)
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);