📄 core_mmst.cpp
字号:
/* These header types correspond to "H$", "D$" and "E$" (Header, Data and End) */
if ((Type != MMSD_HEADER_CHUNK) && (Type != MMSD_DATA_CHUNK))
{
gui_showstatus(STATUS_ERROR, "Unknown header type: %02X:%02X\n", Type, SubType);
My_ti->Reply = REPLY_FAIL;
//break;
}
/* calculate length of chunk body. */
BodyLength = Length-8;
/* check if the body length exceeds our buffer size */
if ((BodyLength > MAX_CHUNK_SIZE) || (BodyLength <= 0))
{;
gui_showstatus(STATUS_CRITICALERROR, "Illegal ChunkLength. Chunk is %d bytes!\n", Length);
break;
}
/* Read chunk's body data */
Got = readfromstream(&Stream_Parm, Buffer, BodyLength);
if (Type == MMSD_HEADER_CHUNK && My_ti->RequestType == REQUEST_INFORMATION)
{
int Offs;
/* finally got the header */
gui_showstatus(STATUS_INFORMATION, "Received ASF header!\n");
/* find a specific object in this header */
Offs = find_id(ASF_HDR_ID,Buffer, Got);
if (Offs == -1)
{
gui_showstatus(STATUS_CRITICALERROR, "Unable to parse this ASF header!\n");
break;
}
/* extract required information */
My_ci->HeaderOffs = Offs;
//get_quad(&Buffer[Offs+HDR_TOTAL_SIZE_8], &My_ci->TotalSizeHi, &My_ci->TotalSizeLo);
get_quad(&Buffer[Offs+HDR_FINE_TOTALTIME_8], &My_ci->TotalTimeHi, &My_ci->TotalTimeLo);
get_long(&Buffer[Offs+HDR_PLAYTIME_OFFSET_4], &My_ci->Offset);
get_long(&Buffer[Offs+HDR_FLAGS_4], &My_ci->Flags);
get_long(&Buffer[Offs+HDR_ASF_CHUNKLENGTH_4], &My_ci->ChunkLength);
get_long(&Buffer[Offs+HDR_ASF_CHUNKLENGTH_CONFIRM_4], &My_ci->ChunkLength2);
unsigned long NumOfPacket;
get_long(&Buffer[Offs+HDR_NUM_PACKETS_8], &NumOfPacket);
My_ci->TotalSizeLo = BodyLength + NumOfPacket*My_ci->ChunkLength;
My_ci->TotalSizeHi = 0;
My_hi->FileSize = My_ci->TotalSizeLo;
/* check if the extracted chunk length looks good */
if ((My_ci->ChunkLength > MAX_CHUNK_SIZE) && (My_ci->ChunkLength != My_ci->ChunkLength2))
{
gui_showstatus(STATUS_CRITICALERROR, "Illegal chunk sizes, %d, %d\n", My_ci->ChunkLength, My_ci->ChunkLength2);
break;
}
/* calculate playtime in milliseconds (0 for live streams) */
if (My_ci->TotalTimeHi == 0 && My_ci->TotalTimeLo == 0)
My_ci->Time = 0; /* live streams */
else
My_ci->Time = (int)((double)429496.7296 * My_ci->TotalTimeHi) + (My_ci->TotalTimeLo / 10000) - My_ci->Offset;
/* store position where the ASF header segment ends and the chunk data segment starts */
My_ci->EndOfHeaderOffs = BodyLength - DATSEG_HDR_SIZE;
My_ti->Reply = REPLY_OK;
break;
}
/* Try to extract a timecode from all known chunk/content types(only applies to data chunks) */
if (Type == MMSD_DATA_CHUNK)
{
int TCStart;
ustrcpy(TimeCodeString, "?????");
TimeCode = 0;
if (My_ti->RequestType == REQUEST_INFORMATION) continue;
/* save the first seqno available as a reference */
if (StartSeqNO == 0xffffffff) StartSeqNO = SeqNO;
/* fix the seqno for live recordings only */
if (My_ci->Time == 0) SeqNO -= StartSeqNO; /* refer seqno to the point we "zapped in" (for live streams) */
/* find the location of the time code */
if ((TCStart = whereis_timecode(Buffer)) > 0)
{
/* The timecode is an integer value defining milliseconds enough range for about 50 days! */
get_long(&Buffer[TCStart], &TimeCode);
/* save the first timecode available as a reference */
if (StartTime == 0xffffffff) StartTime = TimeCode;
/* fix timecode for live recordings only */
if (My_ci->Time == 0)
{
TimeCode -= StartTime; /* refer timecode to the point we "zapped in" (live streams) */
fix_timecodes(Buffer, BodyLength, StartTime, SeqNO, My_ci); /* fixes the timecodes in the memory buffer */
}
/* save max. timecode value */
if (TimeCode > My_ci->MaxTimeCode)
My_ci->MaxTimeCode = TimeCode;
/* create a string with a human-readable form of the timecode */
ustrcpy(TimeCodeString, createtimestring(TimeCode));
}
}
/* calculate progress indicator (scale: 0....10000) */
if (My_ci->Time == 0) /* this mean a live record */
{
if (My_Job->MaxTime == 0) /* unlimited recording */
Progress = 0;
else /* limited time recording */
Progress = (int)((double)TimeCode*10000/(My_Job->MaxTime*60*1000));
}
else
Progress = (int)(((double)(SeqNO+1)*My_ci->ChunkLength+My_ci->EndOfHeaderOffs+DATSEG_HDR_SIZE) / My_hi->FileSize * 10000);
/* Print current position in stream download */
gui_showstatus(STATUS_INFORMATION, "%d | %7dKB | %3d.%02d%% | HDR:%02X:%02X | %5dBYTES | SEQ:%06X | TC:%s\n",
MyID,
max( (signed long)(SeqNO+1)*My_ci->ChunkLength - My_ti->DestOffset, 0 )/1024 + 1,
Progress / 100,
Progress % 100,
Type, SubType,
BodyLength,
SeqNO,
TimeCodeString );
/* some statistics for data chunks only */
if (Type == MMSD_DATA_CHUNK)
{
/* check chunk body for completeness */
if (Got < BodyLength && My_Job->OutFile != NULL)
{
gui_showstatus(STATUS_ERROR, "Received incomplete chunk... (Chunk is NOT saved)\n");
continue;
}
My_ci->NumDataChunks++; /* count number of chunks */
My_ci->SizeOfDataChunks += My_ci->ChunkLength; /* count total size of chunks */
}
if (My_Job->OutFile != NULL)
{
/* lock other threads from writing */
MUTEX
char ThisChunkFlag;
unsigned char *ThisChunkPtr;
unsigned long ThisChunkPos;
unsigned long ThisChunkSize;
switch (Type)
{
case MMSD_HEADER_CHUNK:
ThisChunkPos = 0;
ThisChunkPtr = Buffer;
if(My_ti->SourOffset == 0) /* Is this the request for first segment? */
{
unsigned char c1=0, c2=0, c3=0, c4=0;
/* a dirty hack to find all "MP43" and change to "DIV3" in header */
for ( i=0 ; i<=Got ; ++i ) {
c4=c3 ; c3=c2 ; c2=c1;
c1=Buffer[i];
if( 'M'==c4 && 'P'==c3 && '4'==c2 && '3'==c1 ) {
Buffer[i-3]='D';
Buffer[i-2]='I';
Buffer[i-1]='V';
Buffer[i]='3';
}
}
ThisChunkSize = Got;
}
else
ThisChunkSize = 0; /* Just ignore it */
break;
case MMSD_DATA_CHUNK:
/* calculate appropriate position in file */
ThisChunkPos = My_ci->EndOfHeaderOffs + DATSEG_HDR_SIZE + SeqNO * My_ci->ChunkLength;
ThisChunkSize = My_ci->ChunkLength;
ThisChunkPtr = Buffer;
/* Get Data chunk's Padding Flags. */
ThisChunkFlag = Buffer[3];
/* Convert 0x40 chunk to Non-0x40 form, VirtualDub dont recognize this type */
if (ThisChunkFlag & 0x40)
{
for (i=5 ; i<Got ; i++) Buffer[i]=Buffer[i+2];
Buffer[3] = ThisChunkFlag - 0x40;
Got -= 2;
BodyLength -= 2;
}
/* Fix the padding size. */
if (ThisChunkFlag & 0x18)
{
short int PaddingSize = ThisChunkSize-BodyLength;
Buffer[5] = (char)(PaddingSize & 0xff);
if (ThisChunkFlag & 0x10) Buffer[6]=(char)(PaddingSize >> 8);
}
/* Fill up unused bytes in this chunk. ASF requires equally sized DATA chunks */
memset((char *)(ThisChunkPtr + Got), 0, (ThisChunkSize - Got));
break;
default:
ThisChunkPos = MyFilePointer;
ThisChunkSize = Got;
ThisChunkPtr = Buffer;
}
/* Since the server always send a full chunk, We sometimes just need latter part of this chunk */
if (ThisChunkPos < My_ti->SourOffset)
{
if ((ThisChunkPos + ThisChunkSize) < My_ti->SourOffset)
{
if(Type != MMSD_HEADER_CHUNK) gui_showstatus(STATUS_INFORMATION, "(%d) Chunk position below range, ignored.\n", MyID);
ThisChunkPos = 0;
ThisChunkSize = 0;
}
else
{
ThisChunkPtr += (My_ti->SourOffset - ThisChunkPos);
ThisChunkSize -= (My_ti->SourOffset - ThisChunkPos);
ThisChunkPos = My_ti->SourOffset;
}
}
/* We sometimes just need header part of this chunk */
if ((ThisChunkPos + ThisChunkSize) > (My_ti->SourOffset + My_ti->DestLength))
{
if (ThisChunkPos > (My_ti->SourOffset + My_ti->DestLength))
{
gui_showstatus(STATUS_INFORMATION, "(%d) Chunk position over range, ignored.\n", MyID);
ThisChunkPos = 0;
ThisChunkSize = 0;
}
else
{
//printf("ID:%d Offse:%d Length:%d ThisChunkSize:%d ThisChunkPos:%d\n", MyID, My_ti->SourOffset, My_ti->DestLength, ThisChunkSize, ThisChunkPos);
ThisChunkSize -= ((ThisChunkPos + ThisChunkSize) - (My_ti->SourOffset + My_ti->DestLength));
}
}
/* perform write action */
fseek(My_Job->OutFile, ThisChunkPos-My_ti->DestOffset, SEEK_SET);
fwrite(ThisChunkPtr, ThisChunkSize, 1, My_Job->OutFile);
MyFilePointer = ThisChunkPos + ThisChunkSize;
My_ti->SourOffset += ThisChunkSize;
My_ti->DestLength -= ThisChunkSize;
//printf("ID:%d Offse:%d Length:%d ThisChunkSize:%d ThisChunkPos:%d\n", MyID, My_ti->SourOffset, My_ti->DestLength, ThisChunkSize, ThisChunkPos);
/* unlock other threads */
DEMUTEX
}
/* set a new total time for the stream (important for preview and slider functionality)
if (My_ci->Time == 0)
{
if (My_Job->MaxTime == 0)
gui_modify_duration(TimeCode);
else
gui_modify_duration(My_Job->MaxTime*60*1000);
} */
/* Check whether dest_length reached */
if( !My_ti->DestLength )
{
gui_showstatus(STATUS_INFORMATION, "Segment finished.\n");
My_ti->Reply = REPLY_SEGMENTFINISH;
break;
}
/* use recording time limit, if specified */
if ( (My_Job->MaxTime != 0) && ((int)TimeCode >= (My_Job->MaxTime*60*1000)) )
{
My_ti->DestLength = 0;
gui_showstatus(STATUS_INFORMATION, "maxtime reached.\n");
My_ti->Reply = REPLY_EXIT;
break;
}
/* Receive Message from Job */
if(My_ti->Message == MESSAGE_PAUSE)
while(My_ti->Message != MESSAGE_CONTINUE) usleep(50);
if(My_ti->Message == MESSAGE_EXIT || My_ti->Message == MESSAGE_CANCEL)
{
My_ti->Reply = REPLY_EXIT;
break;
}
} /* for (;;) */
/* Cleanup stream */
my_closesocket(ConnSocket);
free(Stream_Parm.si);
break;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
case REQUEST_FINISH:
{
/* fix total file size and for live streams the header information as well */
if ( My_Job->OutFile != NULL )
{
unsigned long FileSizeHi = 0;
unsigned long FileSizeLo;
/* Determine file size of .ASF file */
fseek(My_Job->OutFile, 0, SEEK_END);
FileSizeLo = ftell(My_Job->OutFile);
/* write correct file size in ASF header */
fseek(My_Job->OutFile, My_ci->HeaderOffs + HDR_TOTAL_SIZE_8, SEEK_SET);
write_quad(My_Job->OutFile, FileSizeHi, FileSizeLo);
/* enable seeking in file */
fseek(My_Job->OutFile, My_ci->HeaderOffs + HDR_FLAGS_4, SEEK_SET);
write_long(My_Job->OutFile, 0x00000002);
}
break;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
} /* switch(RequestType)*/
/* Cleanup & exit */
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -