/* * Copyright (c) 2011, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include "demux.h" #include "util.h" char mpeg4head[45] = {0,0,0,0}; int esds_length; unsigned char *esds_data; extern int first_in_buff; int get_esds_offset(const char *filename); static AVFormatContext * open_file(const char *filename) { AVFormatContext *afc; int err = av_open_input_file(&afc, filename, NULL, 0, NULL); if (!err) err = av_find_stream_info(afc); if (err < 0) { ERROR("%s: lavf error %d", filename, err); exit(1); } dump_format(afc, 0, filename, 0); return afc; } static AVStream * find_stream(AVFormatContext *afc) { AVStream *st = NULL; unsigned int i; for (i = 0; i < afc->nb_streams; i++) { if (afc->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && !st) st = afc->streams[i]; else afc->streams[i]->discard = AVDISCARD_ALL; } return st; } static struct demux * open_stream(const char * filename, int *width, int *height) { AVFormatContext *afc = open_file(filename); AVStream *st = find_stream(afc); AVCodecContext *cc = st->codec; AVBitStreamFilterContext *bsf = NULL; struct demux *demux; if ((cc->codec_id != CODEC_ID_H264) && (cc->codec_id != CODEC_ID_MPEG2VIDEO) && ( cc->codec_id != CODEC_ID_MPEG4)){ ERROR("could not open '%s': unsupported codec %d", filename, cc->codec_id); return NULL; } if (cc->extradata && cc->extradata_size > 0 && cc->extradata[0] == 1) { MSG("initializing bitstream filter"); bsf = av_bitstream_filter_init("h264_mp4toannexb"); if (!bsf) { ERROR("could not open '%s': failed to initialize bitstream filter", filename); return NULL; } } *width = cc->width; *height = cc->height; demux = calloc(1, sizeof(*demux)); demux->afc = afc; demux->cc = cc; demux->st = st; demux->bsf = bsf; return demux; } struct demux * demux_init(const char * filename, int *width, int *height) { av_register_all(); avcodec_register_all(); if(get_esds_offset(filename)) return NULL; return open_stream(filename, width, height); } int get_esds_offset(const char *filename) { FILE *inputStream; int i=0; unsigned char *buffer = NULL; unsigned long fileLen; int esds_index=0; inputStream = fopen(filename,"rb"); if (!inputStream) { printf("Unable to open %s\n",filename); return -1; } // Get the length fseek(inputStream, 0, SEEK_END); fileLen=ftell(inputStream); fseek(inputStream, 0, SEEK_SET); buffer=malloc(fileLen); if (!buffer) { printf("Memory error!\n"); fclose(inputStream); return -1; } // File to buffer fread(buffer, fileLen, 1, inputStream); fclose(inputStream); printf("Buffer starts: %p\n", &buffer[0]); printf("Buffer ends: %p\n", &buffer[fileLen]); //Determines offset of known_string for(i=0; iafc, &pk)) { if (pk.stream_index == demux->st->index) { uint8_t *buf; int bufsize; if (demux->bsf) { int ret; ret = av_bitstream_filter_filter(demux->bsf, demux->cc, NULL, &buf, &bufsize, pk.data, pk.size, 0); if (ret < 0) { ERROR("bsf error: %d", ret); return 0; } } else { buf = pk.data; bufsize = pk.size; } if (bufsize > size) bufsize = size; if(first_in_buff == 1) { memcpy(input,esds_data,esds_length); memcpy(input+esds_length, buf, bufsize); first_in_buff =0; bufsize = bufsize+esds_length; } else { memcpy(input, buf, bufsize); } if (demux->bsf) av_free(buf); av_free_packet(&pk); return bufsize; } av_free_packet(&pk); } return 0; } int demux_rewind(struct demux *demux) { return av_seek_frame(demux->afc, demux->st->index, 0, AVSEEK_FLAG_FRAME); } void demux_deinit(struct demux *demux) { av_close_input_file(demux->afc); if (demux->bsf) av_bitstream_filter_close(demux->bsf); free(esds_data); free(demux); }