00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <liveMedia.hh>
00026 #include <BasicUsageEnvironment.hh>
00027
00028 void afterPlaying(void* clientData);
00029
00030 UsageEnvironment* env;
00031 char const* programName;
00032
00033 void usage() {
00034 *env << "usage: " << programName << " <input-transport-stream-file-name> <start-time> <scale> <output-transport-stream-file-name>\n";
00035 *env << "\twhere\t<transport-stream-file-name> ends with \".ts\"\n";
00036 *env << "\t\t<start-time> is the starting play time in seconds (0 for the start)\n";
00037 *env << "\t\t<scale> is a non-zero integer, representing the playing speed (use 1 for normal play; use a negative number for reverse play)\n";
00038 exit(1);
00039 }
00040
00041 int main(int argc, char const** argv) {
00042
00043 TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00044 env = BasicUsageEnvironment::createNew(*scheduler);
00045
00046
00047 programName = argv[0];
00048 if (argc != 5) usage();
00049
00050 char const* inputFileName = argv[1];
00051
00052 int len = strlen(inputFileName);
00053 if (len < 4 || strcmp(&inputFileName[len-3], ".ts") != 0) {
00054 *env << "ERROR: input file name \"" << inputFileName
00055 << "\" does not end with \".ts\"\n";
00056 usage();
00057 }
00058
00059
00060 float startTime;
00061 if (sscanf(argv[2], "%f", &startTime) != 1 || startTime < 0.0f) usage();
00062
00063 int scale;
00064 if (sscanf(argv[3], "%d", &scale) != 1 || scale == 0) usage();
00065
00066
00067 FramedSource* input
00068 = ByteStreamFileSource::createNew(*env, inputFileName, TRANSPORT_PACKET_SIZE);
00069 if (input == NULL) {
00070 *env << "Failed to open input file \"" << inputFileName << "\" (does it exist?)\n";
00071 exit(1);
00072 }
00073
00074
00075
00076 char* indexFileName = new char[len+2];
00077 sprintf(indexFileName, "%sx", inputFileName);
00078 MPEG2TransportStreamIndexFile* indexFile
00079 = MPEG2TransportStreamIndexFile::createNew(*env, indexFileName);
00080 if (indexFile == NULL) {
00081 *env << "Failed to open index file \"" << indexFileName << "\" (does it exist?)\n";
00082 exit(1);
00083 }
00084
00085
00086 MPEG2TransportStreamTrickModeFilter* trickModeFilter
00087 = MPEG2TransportStreamTrickModeFilter::createNew(*env, input, indexFile, scale);
00088
00089 if (startTime > 0.0f) {
00090
00091 unsigned long tsRecordNumber, indexRecordNumber;
00092 indexFile->lookupTSPacketNumFromNPT(startTime, tsRecordNumber, indexRecordNumber);
00093 if (!trickModeFilter->seekTo(tsRecordNumber, indexRecordNumber)) {
00094 *env << "Failed to seek trick mode filter to ts #" << (unsigned)tsRecordNumber
00095 << ", ix #" << (unsigned)indexRecordNumber
00096 << "(for time " << startTime << ")\n";
00097 exit(1);
00098 }
00099 }
00100
00101
00102 MPEG2TransportStreamFromESSource* newTransportStream
00103 = MPEG2TransportStreamFromESSource::createNew(*env);
00104 newTransportStream->addNewVideoSource(trickModeFilter, indexFile->mpegVersion());
00105
00106
00107 char const* outputFileName = argv[4];
00108 MediaSink* output = FileSink::createNew(*env, outputFileName);
00109 if (output == NULL) {
00110 *env << "Failed to open output file \"" << outputFileName << "\"\n";
00111 exit(1);
00112 }
00113
00114
00115 *env << "Writing output file \"" << outputFileName
00116 << "\" (start time " << startTime
00117 << ", scale " << scale
00118 << ")...";
00119 output->startPlaying(*newTransportStream, afterPlaying, NULL);
00120
00121 env->taskScheduler().doEventLoop();
00122
00123 return 0;
00124 }
00125
00126 void afterPlaying(void* ) {
00127 *env << "...done\n";
00128 exit(0);
00129 }