testProgs/testMPEG2TransportStreamTrickPlay.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // Copyright (c) 1996-2012, Live Networks, Inc.  All rights reserved
00017 // A program that tests 'trick mode' operations on a MPEG-2 Transport Stream file,
00018 // by generating a new Transport Stream file that represents the result of the
00019 // 'trick mode' operation (seeking and/or fast forward/reverse play).
00020 // For this to work, there must also be an index file present, in the same directory
00021 // as the Transport Stream file, and with the same name prefix.  (The Transport
00022 // Stream file has name suffix ".ts"; the index file has name suffix ".tsx".)
00023 // main program
00024 
00025 #include <liveMedia.hh>
00026 #include <BasicUsageEnvironment.hh>
00027 
00028 void afterPlaying(void* clientData); // forward
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   // Begin by setting up our usage environment:
00043   TaskScheduler* scheduler = BasicTaskScheduler::createNew();
00044   env = BasicUsageEnvironment::createNew(*scheduler);
00045 
00046   // Parse the command line:
00047   programName = argv[0];
00048   if (argc != 5) usage();
00049 
00050   char const* inputFileName = argv[1];
00051   // Check whether the input file name ends with ".ts":
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   // Parse the <start-time> and <scale> parameters:
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   // Open the input file (as a 'byte stream file source'):
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   // Check whether the corresponding index file exists.
00075   // The index file name is the same as the input file name, except with suffix ".tsx":
00076   char* indexFileName = new char[len+2]; // allow for trailing x\0
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   // Create a filter that generates trick mode data from the input and index files:
00086   MPEG2TransportStreamTrickModeFilter* trickModeFilter
00087     = MPEG2TransportStreamTrickModeFilter::createNew(*env, input, indexFile, scale);
00088 
00089   if (startTime > 0.0f) {
00090     // Seek the input Transport Stream and Index files to the specified start time:
00091     unsigned long tsRecordNumber, indexRecordNumber;
00092     indexFile->lookupTSPacketNumFromNPT(startTime, tsRecordNumber, indexRecordNumber);
00093     if (!trickModeFilter->seekTo(tsRecordNumber, indexRecordNumber)) { // TARFU!
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   // Generate a new Transport Stream from the Trick Mode filter:
00102   MPEG2TransportStreamFromESSource* newTransportStream
00103     = MPEG2TransportStreamFromESSource::createNew(*env);
00104   newTransportStream->addNewVideoSource(trickModeFilter, indexFile->mpegVersion());
00105 
00106   // Open the output file (for writing), as a 'file sink':
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   // Start playing, to generate the output file:
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(); // does not return
00122 
00123   return 0; // only to prevent compiler warning
00124 }
00125 
00126 void afterPlaying(void* /*clientData*/) {
00127   *env << "...done\n";
00128   exit(0);
00129 }

Generated on Thu May 17 07:11:48 2012 for live by  doxygen 1.5.2