⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core_mmst.cpp

📁 ASFR+是在ASFRecorder的基础上的改进版本,它可以: ◇支持中文文件名. ◇多线程下载ASF文件. ◇断点续传,自动重试. ◇支持MMS(TCP)协议和HTTP协议(自动探测). ◇在下载
💻 CPP
📖 第 1 页 / 共 2 页
字号:
				/* 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 + -