a77bbb8746ceed6e9fe571928bd4f56ba5c4bd1d
[glsdk/omapdrmtest.git] / util / demux.c
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;
115 struct demux * demux_init(const char * filename, int *width, int *height)
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;
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;
178 int demux_read(struct demux *demux, char *input, int size)
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;
226 int demux_rewind(struct demux *demux)
228         return av_seek_frame(demux->afc, demux->st->index, 0, AVSEEK_FLAG_FRAME);
231 void demux_deinit(struct demux *demux)
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);