123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "avi_demuxer.h"
- #include <stream.h>
- unsigned int Samples_per_sec;
- /**
- ** 读取4 个字节
- **/
- int read4bytes(void *stream)
- {
- DWORD val;
- int rdnum;
-
- rdnum = read_data(stream, &val, 4);
- if (rdnum != 4)
- {
- val = 0;
- }
- return val;
- }
- FOURCC check_junk(void *stream, FOURCC tag, FOURCC compare_tag)
- {
- int curtag;
- int junklen;
- if (tag != compare_tag)
- return tag;
-
- junklen = read4bytes(stream);
- read_skip(stream, junklen);
- curtag = read4bytes(stream);
- curtag = check_junk(stream, curtag, compare_tag);
- return curtag;
- }
- /**
- ** 分析视频文件头,获取必要信息
- **/
- int read_header(void *avict)
- {
- //amv len is set to 0 so we can skip zero
- //make it simple just do the amv case
- //riff len avi
- //list len hdrl
- //avih len mainAVIHeader
- //list len strl
- //strh len AVIStreamHeader
- //strf len BITMAPINFORHEADER or WAVEFORMATEX
- //riff len avi or riff 0 amv
- FOURCC tag;
- MainAVIHeader mheader;
- AVIStreamHeader sheader;
- int rdnum;
- //BITMAPINFOHEADER bmpinfo;
- //WAVEFORMATEX waveinfo;
- io_stream_t stream;
- avi_contex_t *ac;
- //int junklen;
- FOURCC contag;
- int strhlen;
- int strflen;
- int movi_len;
- if (avict == NULL)
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return MEMERROR;
- }
-
- ac = (avi_contex_t *)avict;
-
- stream = ac->stream;
-
- read_skip(stream, 8); //riff len
-
- tag = read4bytes(stream);
- if ((tag != formtypeAVI)&&(tag != formtypeAMV))
- {
- printf("%s: tag: 0x%x\n", __FUNCTION__, tag);
- return UNKNOWNCON;
- }
-
- contag = tag;
-
- if (contag == formtypeAMV)
- {
- // 视频文件为amv 格式
- ac->amvformat = 1;
- }
-
- read_skip(stream, 12); //list len hdrl
-
- tag = read4bytes(stream);
-
- //if (tag != ckidAVIMAINHDR) //avih len mainAVIHeader
- // return UNKNOWNCON;
- read_skip(stream, 4);
-
- rdnum = read_data(stream, &mheader, sizeof(MainAVIHeader));
- if (rdnum != sizeof(MainAVIHeader))
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return STREAMEND;
- }
-
- if (ac->amvformat)
- {
- // AMV Format
- int fps = 0;
- int timedur = 0;
- int timeval = mheader.dwReserved[3];
- // 帧率,每秒帧数
- fps = mheader.dwReserved[0]; //dwRate
- // 视频时长hh:mm:ss,转成秒
- timedur = (timeval&0xff) + ((timeval>>8)&0xff)*60 + ((timeval>>16)&0xff)*3600;
- // 视频总帧数
- ac->TotalFrames = timedur * fps;
- ac->dwScale = mheader.dwReserved[1];
- ac->dwRate = mheader.dwReserved[0];
- }
- else
- {
- // AVI Format
- ac->TotalFrames = mheader.dwTotalFrames;
- }
-
- ac->index_flag = mheader.dwFlags;
- ac->bmpheader.biWidth = mheader.dwWidth;
- ac->bmpheader.biHeight = mheader.dwHeight;
-
- do{
-
- tag = read4bytes(stream);
-
- tag = check_junk(stream, tag, ckidAVIPADDING);
-
- if (tag != LISTTAG)
- break;
-
- movi_len = read4bytes(stream);
- tag = read4bytes(stream);
- if (tag == listtypeAVIMOVIE)
- {
- ac->movitagpos = file_tell(stream) ;
- ac->index_offset = movi_len+ac->movitagpos - 4;
- //相对偏移起始位置
- break;
- }
-
- tag = read4bytes(stream);
- if (tag != ckidSTREAMHEADER) //strh len AVIStreamHeader
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return UNKNOWNCON;
- }
- strhlen = read4bytes(stream);
- memset(&sheader, 0, sizeof(AVIStreamHeader));
-
- if (contag == formtypeAMV)
- {
- read_skip(stream, strhlen);
- }
- else
- {
- rdnum = read_data(stream, &sheader, sizeof(AVIStreamHeader));
-
- if (rdnum != sizeof(AVIStreamHeader))
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return STREAMEND;
- }
- }
-
- tag = read4bytes(stream);
-
- if (tag != (ckidSTREAMFORMAT)) //strf len BITMAPINFORHEADER or WAVEFORMATEX
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return UNKNOWNCON;
- }
- strflen = read4bytes(stream);
-
- if (contag == formtypeAMV)
- {
- if (strflen == 0x14)
- {
- rdnum = read_data(stream, &ac->amvwaveheader, sizeof(AMVAudioStreamFormat));
- if (rdnum != sizeof(AMVAudioStreamFormat))
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return STREAMEND;
- }
- ac->dwSamples_per_sec = ac->amvwaveheader.dwSamples_per_sec;
- ac->wChannels = ac->amvwaveheader.wChannels;
- Samples_per_sec = ac->dwSamples_per_sec;
- }
- else
- {
- read_skip(stream, strflen);
- }
- }
- else
- {
- if (sheader.fccType == streamtypeVIDEO)
- {
- ac->dwScale = sheader.dwScale;
- ac->dwRate = sheader.dwRate;
- rdnum = read_data(stream, &ac->bmpheader, sizeof(BITMAPINFOHEADER));
- if (rdnum != sizeof(BITMAPINFOHEADER))
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return STREAMEND;
- }
- }
-
- if (sheader.fccType == streamtypeAUDIO)
- {
- rdnum = read_data(stream, &ac->waveheader, sizeof(WAVEFORMATEX));
- if (rdnum != sizeof(WAVEFORMATEX))
- {
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return STREAMEND;
- }
- ac->dwSamples_per_sec = ac->waveheader.nSamplesPerSec;
- ac->wChannels = ac->waveheader.nChannels;
- Samples_per_sec = ac->dwSamples_per_sec;
- read_skip(stream, ac->waveheader.cbSize);
- }
- }
- }while(1);
- printf("%s: %d\n", __FUNCTION__, __LINE__);
- return NORMAL;
- }
- int get_es_chunk(void *avict, avi_packet_t *raw_packet)
- {
- FOURCC tag;
- //int rdnum;
- void *stream;
- avi_contex_t *ac;
- int chunklen;
- //int d[8];
- //int i,n;
- //int size;
- //unsigned char val;
-
- if ((avict == NULL)||(raw_packet == NULL))
- return MEMERROR;
- ac = (avi_contex_t *)avict;
-
- stream = ac->stream;
- tag = read4bytes(stream);
- if (tag == 0)
- return STREAMEND;
- //tag = check_junk(io, tag, ckidAVIPADDING);
- //get chunk type
- switch ((tag >> 16) & DATA_MASK)
- {
- case cktypeDIBbits:
- case cktypeDIBcompressed:
- raw_packet->es_type = streamtypeVIDEO;
- //printf("f pos: 0x%x\n", file_tell(io) - 4);
- break;
- case cktypeWAVEbytes:
- raw_packet->es_type = streamtypeAUDIO;
- break;
- default:
- raw_packet->es_type = tag;
- break;
- }
- //read chunk
- chunklen = read4bytes(stream);
- raw_packet->data_len = chunklen;
- raw_packet->pts = ((ac->framecounter * TIMESCALE * 10) / ac->framerate)/10;
- return NORMAL;
-
- }
- typedef struct{
- int frameth;
- DWORD pos;
- }frame_info_t;
- #define SCAN_BUF_LEN (MAX_PACKET_LEN-3)
- int search_es_chunk(void *avict, avi_packet_t *raw_packet)
- {
- FOURCC tag;
- //FOURCC Firsttag;
- //int rdnum;
- void *stream;
- avi_contex_t *ac;
- //int chunklen;
- //int d[8];
- //int i,n;
- int size;
- //unsigned char val;
- int frame_num;
- frame_info_t frame_arr[10];
- int offsettostart;
- unsigned char paddbytes[3];
- unsigned char *tmpbuf = 0;
- int end;
- unsigned char *ptr;
- int buf_remain;
- int flag_start;
-
- if ((avict == NULL)||(raw_packet == NULL))
- return MEMERROR;
- ac = (avi_contex_t *)avict;
-
- stream = ac->stream;
- flag_start = 0;
- frame_num = 0;
- paddbytes[0] = 0;
- paddbytes[1] = 0;
- paddbytes[2] = 0;
- //外部传入,就是av_buf里的缓冲区
- tmpbuf = raw_packet->data;
- GETMOREDATA:
- //ac->movitagpos;
-
- //offsettostart = file_tell(io);
- offsettostart = file_tell(stream);
- if (offsettostart <= ac->movitagpos)
- return STREAMSTART;
- offsettostart -= ac->movitagpos;
-
- if (offsettostart > SCAN_BUF_LEN)
- {
- file_seek_back(stream, -SCAN_BUF_LEN);
- read_data(stream, tmpbuf, SCAN_BUF_LEN);
- end = SCAN_BUF_LEN;
- file_seek_back(stream, -SCAN_BUF_LEN);
- }
- else
- {
- file_seek_back(stream, -offsettostart);
- read_data(stream, tmpbuf, offsettostart);
- end = offsettostart;
- flag_start = 1;
- file_seek_back(stream, -offsettostart);
- }
-
- //seek -(5k or less 5k)
- tmpbuf[end + 0] = paddbytes[0];
- tmpbuf[end + 1] = paddbytes[1];
- tmpbuf[end + 2] = paddbytes[2];
- ptr = tmpbuf;
- buf_remain = end + 3;
-
- while(1)
- {
- if (buf_remain <= 3){
- paddbytes[0] = tmpbuf[0];
- paddbytes[1] = tmpbuf[1];
- paddbytes[2] = tmpbuf[2];
- //reget buf;
- if (frame_num)
- goto SACN_END;
-
- if (flag_start)
- return STREAMSTART;
-
- goto GETMOREDATA;
- }
-
- if (*ptr != 0x30){ //30 is '0'
- ptr++;
- buf_remain--;
- continue;
- }
-
- if (buf_remain > 3)
- tag = ptr[0] + (ptr[1]<<8) + (ptr[2]<<16) + (ptr[3]<<24);
- else
- continue;
-
- switch (tag)
- {
- case 0x63643030:
- frame_arr[frame_num].pos = file_tell(stream) + (ptr - (unsigned char *)tmpbuf);
-
- if (frame_num >= 10)
- return NORMAL;
- frame_num++;
-
- if (buf_remain > 7){
- size = ptr[4] + (ptr[5]<<8) + (ptr[6]<<16) + (ptr[7]<<24);
- if ((buf_remain - 8) >= size){
- ptr += (8 + size);
- buf_remain -= (8 + size);
- }
- else
- buf_remain = 0;
- }
- else{
- ptr += 4;
- buf_remain -=4;
- }
-
- break;
- default:
- ptr++;
- buf_remain--;
- break;
-
- }
- }
- SACN_END:
- if (frame_num > 0)
- {
- int i;
- //get frameth
- for(i = 0; i < frame_num;i++)
- {
- frame_arr[i].frameth = ac->framecounter - (frame_num - i);
- //save to index
- }
- ac->framecounter = frame_arr[frame_num - 1].frameth;
- file_seek_set(stream, frame_arr[frame_num - 1].pos);
- //printf("b pos: 0x%x\n", frame_arr[frame_num - 1].pos);
- raw_packet->pts = ((ac->framecounter * TIMESCALE * 10) / ac->framerate )/ 10;
- }
-
- return NORMAL;
-
- }
|