📄 asffile.c
字号:
asf->m_video_packet->num_segments = 1;
if ((asf->m_video_packet->flags & 0x01) != 0) /* multiple payloads */
{
asf->m_video_packet->num_segments = ASF_Read8(asf);
asf->m_video_packet->seglentype = (asf->m_video_packet->num_segments >> 6);
asf->m_video_packet->num_segments &= 0x3F;
asf->m_video_packet->packet_size--;
}
ASF_DEBUG("Read %lu bytes - pad_size = %lu\n", asf->m_read_bytes, asf->m_video_packet->pad_size);
return TRUE;
}
static gboolean
ASF_GetNextSegment(ASF_DEMUX * asf)
{
guint32 seg_info_len;
//guint32 frag_dep;
//ASF_Segment *asf_segment;
//ASF_Stream *s;
guint32 ret;
if (asf->m_video_seg->compressed)
{
/* read all compressed payload out. */
if (asf->m_video_seg->m_length > asf->m_max_packet_size)
return FALSE;
if (asf->m_video_seg->m_length > 1)
{
asf->m_video_seg->data_length = ASF_Read8(asf);
if (asf->m_video_seg->m_length > asf->m_video_seg->data_length)
{
asf->m_video_seg->object_length = asf->m_video_seg->data_length;
asf->m_video_seg->m_length -= asf->m_video_seg->data_length + 1;
asf->m_video_seg->object_start += asf->m_video_seg->time_delta;
asf->m_video_seg->m_object_id ++;
ASF_DEBUG("sub_segment_start = %lu\n", asf->m_video_seg->object_start);
return TRUE;
}
else
{
ASF_Skip(asf, asf->m_video_seg->m_length);
asf->m_video_seg->compressed = 0;
}
}
else
{
asf->m_video_seg->compressed = 0;
}
}
if (!asf->m_video_packet->num_segments)
{
ASF_Skip(asf, asf->m_video_packet->pad_size);
if (!ASF_GetNextPacket(asf))
return FALSE;
}
/* Contain key frame flag */
asf->m_video_seg->m_stream_no = ASF_Read8(asf); // & 0x7F;
asf->m_video_packet->packet_size--;
asf->m_video_seg->m_object_id = ASF_FilteredRead(asf, asf->m_video_packet->segment_id >> 4, &asf->m_video_packet->packet_size);
asf->m_video_seg->m_offset = ASF_FilteredRead(asf, asf->m_video_packet->segment_id >> 2, &asf->m_video_packet->packet_size);
seg_info_len = ASF_FilteredRead(asf, asf->m_video_packet->segment_id, &asf->m_video_packet->packet_size);
if (seg_info_len == 0)
return FALSE;
if (seg_info_len == 1)
{
asf->m_video_seg->compressed = TRUE;
#if 0
/* Skip PTS */
ASF_Skip(asf, 1);
#else
/* read pts */
asf->m_video_seg->time_delta = ASF_Read8(asf);
asf->m_video_seg->object_start = asf->m_video_seg->m_offset;
#endif
ASF_DEBUG("found compressed payload.\n");
}
else
{
if (seg_info_len >= 8)
{
asf->m_video_seg->object_length = ASF_Read32(asf);
asf->m_video_seg->object_start = ASF_Read32(asf);
ASF_Skip(asf, seg_info_len - 8);
}
else
{
/* bad information */
printf("Bad Segment Info Length (<= 8)\n");
asf->m_video_seg->object_length = 0;
asf->m_video_seg->object_start = 0;
ASF_Skip(asf, seg_info_len);
}
asf->m_video_packet->packet_size -= seg_info_len;
}
/* Object length */
ASF_DEBUG("object_length = %lu; packet_size = %lu\n", asf->m_video_seg->object_length, asf->m_video_packet->packet_size);
/* Object start time, millisecond */
ASF_DEBUG("object_start = %lu\n", asf->m_video_seg->object_start);
if ((asf->m_video_packet->flags & 0x01) != 0)
{
/* multiple payloads */
ret = 0;
asf->m_video_seg->m_length = ASF_FilteredRead(asf, asf->m_video_packet->seglentype, &ret);
if (ret == 0)
asf->m_video_seg->m_length = asf->m_video_packet->packet_size;
else
asf->m_video_packet->packet_size += ret;
}
else
{
/* single payload */
asf->m_video_seg->m_length = asf->m_video_packet->packet_size;
}
ASF_DEBUG("Data length = %lu\n", asf->m_video_seg->m_length);
asf->m_video_packet->packet_size -= asf->m_video_seg->m_length;
if (asf->m_video_seg->compressed)
{
/* compressed payload */
asf->m_video_seg->data_length = ASF_Read8(asf);
asf->m_video_seg->object_length = asf->m_video_seg->data_length;
asf->m_video_seg->m_length -= asf->m_video_seg->data_length + 1;
}
else
{
/* noncompressed payload */
asf->m_video_seg->data_length = asf->m_video_seg->m_length;
asf->m_video_seg->m_length = 0;
}
asf->m_video_packet->num_segments--;
return TRUE;
}
static __inline void ASF_FillFrmHdr(ASF_DEMUX *asf, unsigned char *buf)
{
*buf++ = 'W';
*buf++ = 'M';
*buf++ = 'V';
*buf++ = 'V';
#if 0
*(guint32 *)buf = asf->m_video_seg->object_length; /* frame size */
buf += 4;
*(guint32 *)buf = asf->m_video_seg->object_start; /* time stamp */
#else
*buf++ = (asf->m_video_seg->object_length & 0xff);
*buf++ = ((asf->m_video_seg->object_length >> 8) & 0xff);
*buf++ = ((asf->m_video_seg->object_length >> 16) & 0xff);
*buf++ = (asf->m_video_seg->object_length >> 24);
*buf++ = (asf->m_video_seg->object_start & 0xff);
*buf++ = ((asf->m_video_seg->object_start >> 8) & 0xff);
*buf++ = ((asf->m_video_seg->object_start >> 16) & 0xff);
*buf++ = (asf->m_video_seg->object_start >> 24);
#endif
asf->m_time_stamp_bak = asf->m_video_seg->object_start;
ASF_DEBUG(" *** Frame: %d, length: %d, time stamp: %d \n",
asf->m_video_seg->m_object_id, asf->m_video_seg->object_length,
asf->m_video_seg->object_start);
asf->m_object_id_bak = asf->m_video_seg->m_object_id;
}
static int ASF_FindNextKeyFrm(ASF_DEMUX *asf)
{
while ((!(asf->m_video_seg->m_stream_no & 0x80)) || ((asf->m_video_seg->m_offset) && (!asf->m_video_seg->compressed))
|| ((asf->m_video_seg->m_stream_no & 0x7f) != asf->m_video_stream->m_stream_id))
{
ASF_Skip(asf, asf->m_video_seg->data_length);
if (!ASF_GetNextSegment(asf))
{
return 0;
}
}
return 1;
}
int ASF_ReadData(ASF_DEMUX *asf, unsigned char *buf, gint32 size, guint16 m_stream_id)
{
guint32 getBytes = 0, readSize;
while (size)
{
while ((!asf->m_video_seg->data_length))
{
if ((!ASF_GetNextSegment(asf)) || (asf->m_error))
return getBytes;
if ((asf->m_video_seg->m_stream_no & 0x7f) != m_stream_id/*asf->m_video_stream->m_stream_id*/)
{
/* skip data of other stream */
ASF_Skip(asf, asf->m_video_seg->data_length);
asf->m_video_seg->data_length = 0;
}
else if (asf->m_video_seg->m_object_id != asf->m_object_id_bak) /* new frame */
{
/* fill frame header, if it is a new frame. */
if (getBytes&0x1)
{
buf[getBytes] = 0; /* use this to keep frame header word align. */
getBytes++;
size--;
}
if (asf->m_ffd_flag)
{
if ((!(asf->m_video_seg->m_stream_no & 0x80))
|| ((asf->m_video_seg->object_start - asf->m_time_stamp_bak) < asf->m_ffd_interval))
{
ASF_Skip(asf, asf->m_video_seg->data_length);
asf->m_video_seg->data_length = 0;
continue;
}
//asf->m_ffd_flag = 0;
}
if (asf->m_seek_flag)
{
AsfFastFseek(asf->m_input, asf->m_seek_dest.Offset, asf->m_seek_dest.Clus);
memcpy(&(asf->m_bits_packet), &(asf->m_seek_packet), sizeof(ASF_Packet));
memcpy(&(asf->m_bits_seg), &(asf->m_seek_seg), sizeof(ASF_Segment));
asf->m_seek_flag = 0;
}
if (((asf->m_video_seg->m_offset) && (!asf->m_video_seg->compressed)) || /* skip bad frame */
((asf->m_object_id_bak == -1) && !(asf->m_video_seg->m_stream_no & 0x80))) /* first frame is not key frame */
{
ASF_Skip(asf, asf->m_video_seg->data_length);
asf->m_video_seg->data_length = 0;
}
else
{
/* fill frame header for new frame. */
if (size < ASF_FRAME_HEADER_SIZE)
{
/* if (remain size to get < size of frame header), fill zero */
memset(&buf[getBytes], 0, size);
getBytes += size;
asf->m_frmhdr_flag = 1; /* set this to fill frame header in next block */
return getBytes;
}
ASF_FillFrmHdr(asf, &buf[getBytes]);
size -= ASF_FRAME_HEADER_SIZE;
getBytes += ASF_FRAME_HEADER_SIZE;
}
}
}
if (asf->m_frmhdr_flag) /* need fill frame header */
{
ASF_FillFrmHdr(asf, &buf[getBytes]);
size -= ASF_FRAME_HEADER_SIZE;
getBytes += ASF_FRAME_HEADER_SIZE;
asf->m_frmhdr_flag = 0;
}
if (size <= asf->m_video_seg->data_length)
{
asf->m_read_bytes += size;
readSize = Asf_fread(asf->m_input, &buf[getBytes], size);
size -= readSize;
getBytes += readSize;
asf->m_video_seg->data_length -= readSize;
return getBytes;
}
else
{
asf->m_read_bytes += asf->m_video_seg->data_length;
readSize = Asf_fread(asf->m_input, &buf[getBytes], asf->m_video_seg->data_length);
size -= readSize;
getBytes += readSize;
if (readSize < asf->m_video_seg->data_length)
return getBytes;
asf->m_video_seg->data_length = 0;
}
}
return getBytes;
}
static __inline int ASF_FillFirstBlock(ASF_DEMUX *asf, char *buffer, gulong size)
{
int readSize;
tWMVDecInternalMember WMVDec;
if (size < sizeof(tWMVDecShareMember))
return -1;
*(short *)buffer = (short)asf->m_video_stream->m_type_specific.m_video.m_width; /* width */
buffer += 2;
*(short *)buffer = (short)asf->m_video_stream->m_type_specific.m_video.m_height; /* height */
buffer += 2;
switch (asf->m_video_stream->m_type_specific.m_video.m_encoding)
{
case fccWMV3:
/* fill wmv3 bit stream header */
WMVideoDecDecodeSequenceHeader(&WMVDec, asf->m_video_stream->m_type_specific.m_video.m_extra_data, 1);
memcpy(buffer, &WMVDec, sizeof(tWMVDecShareMember));
buffer += sizeof(tWMVDecShareMember);
break;
case fccWMV2:
WMVideoDecDecodeSequenceHeader(&WMVDec, asf->m_video_stream->m_type_specific.m_video.m_extra_data, 0);
*((short *)buffer)++ = 2; /* CODEC WMV2 */
*((short *)buffer)++ = WMVDec.m_iFrameRate;
*((short *)buffer)++ = WMVDec.m_iBitRate;
*((short *)buffer)++ = WMVDec.m_bRndCtrlOn;
*((short *)buffer)++ = WMVDec.m_bMixedPel;
*((short *)buffer)++ = WMVDec.m_bLoopFilter;
*((short *)buffer)++ = WMVDec.m_bXformSwitch;
*((short *)buffer)++ = WMVDec.m_bXintra8Switch;
*((short *)buffer)++ = WMVDec.m_bFrmHybridMVOn;
*((short *)buffer)++ = WMVDec.m_bDCTTable_MB_ENABLED;
*((short *)buffer)++ = WMVDec.m_iSliceCode;
memset(buffer, 0, sizeof(tWMVDecShareMember) - 22);
buffer += sizeof(tWMVDecShareMember) - 22;
break;
case fccWMV1:
default:
memset(buffer, 0, sizeof(tWMVDecShareMember));
buffer += sizeof(tWMVDecShareMember);
break;
}
readSize = ASF_ReadData(asf, (unsigned char *)buffer, size
- sizeof(tWMVDecShareMember) - 4, asf->m_video_stream->m_stream_id);
return (readSize + sizeof(tWMVDecShareMember) + 4);
return 0;
}
static int ASF_LoadIndex(ASF_DEMUX *asf)
{
guint64 chunk_len;
Asf_fseek(asf->m_input, 0, SEEK_SET);
/* Look for the index chunk */
while (1)
{
ASF_GUID guid;
ASF_ReadGUID(asf, &guid);
if (ASF_DecodeGUID(&guid, NULL) == ASF_GUID_INDEX)
{
chunk_len = ASF_Read64(asf) - 56;
ASF_Skip(asf, 16);
asf->m_index.m_time_interval = (guint32)(ASF_Read64(asf) / 10000);
asf->m_index.m_max_pkt_count = ASF_Read32(asf);
asf->m_index.m_entries_count = ASF_Read32(asf);
ASF_DEBUG("Num of entries %d, time interval %llu\n", asf->m_index.m_entries_count,
asf->m_index.m_time_interval);
if ((asf->m_index.m_entries_count < 10) || (!asf->m_index.m_time_interval))
return 0;
asf->m_index.m_entry =
(ASF_Index_Entry *)MALLOC(asf->m_index.m_entries_count * sizeof(ASF_Index_Entry));
if (asf->m_index.m_entry)
{
Asf_fread(asf->m_input, asf->m_index.m_entry,
asf->m_index.m_entries_count * SIZEOF_INDEX_ENTRY /*sizeof(ASF_Index_Entry)*/);
asf->m_index_flag = TRUE;
}
break;
}
else
{
ASF_DEBUG("GUID: ");
ASF_DEBUG_PRINT_GUID(guid);
chunk_len = ASF_Read64(asf);
ASF_DEBUG("Chunk len %llu\n", chunk_len);
chunk_len -= 24;
/*
* Check chunk length.
* Funny I found this bug, when coding function 'AsfSeekNextKeyFrm' :)
* 2008-6-7, by ljn
*/
if ((chunk_len >= asf->m_input->FileSize) || (chunk_len < 0))
return 0;
ASF_Skip(asf, chunk_len);
if (asf->m_error)
{
//AsfFastFseek(asf->m_input, asf->m_seek_pos[0].Offset, asf->m_seek_pos[0].Clus);
return 0;
}
}
}
//AsfFastFseek(asf->m_input, asf->m_seek_pos[0].Offset, asf->m_seek_pos[0].Clus);
return 1;
}
static int ASF_CreateSeekTab(ASF_DEMUX *asf)
{
int pkt_interval, i, byte_interval;
pkt_interval = (asf->m_num_packets) / ASF_SEEK_POSITION_NUM;
byte_interval = pkt_interval * asf->m_max_packet_size;
asf->m_seek_pos[0].Offset = asf->m_input->Offset;
asf->m_seek_pos[0].Clus = asf->m_input->Clus;
asf->m_seek_pos[0].Time = 0;
for (i = 1; i < ASF_SEEK_POSITION_NUM; i++)
{
/* get next position */
if (byte_interval)
{
AsfFseek(asf->m_input, byte_interval, SEEK_CUR);
}
asf->m_seek_pos[i].Offset = asf->m_input->Offset;
asf->m_seek_pos[i].Clus = asf->m_input->Clus;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -