~vanvugt/ubuntu/oneiric/mediatomb/fix-770964-784431

« back to all changes in this revision

Viewing changes to src/transcoding/transcode_ext_handler.cc

  • Committer: Bazaar Package Importer
  • Author(s): Andres Mejia
  • Date: 2009-04-22 21:39:19 UTC
  • mto: (4.2.1 sid)
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: james.westby@ubuntu.com-20090422213919-52m015y6gcpv1m1g
Tags: upstream-0.12.0~svn2018
ImportĀ upstreamĀ versionĀ 0.12.0~svn2018

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
    Copyright (C) 2005 Gena Batyan <bgeradz@mediatomb.cc>,
8
8
                       Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>
9
9
    
10
 
    Copyright (C) 2006-2008 Gena Batyan <bgeradz@mediatomb.cc>,
 
10
    Copyright (C) 2006-2009 Gena Batyan <bgeradz@mediatomb.cc>,
11
11
                            Sergey 'Jin' Bostandzhyan <jin@mediatomb.cc>,
12
12
                            Leonhard Wimmer <leo@mediatomb.cc>
13
13
    
24
24
    version 2 along with MediaTomb; if not, write to the Free Software
25
25
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
26
26
    
27
 
    $Id: transcode_ext_handler.cc 1698 2008-02-23 20:48:30Z lww $
 
27
    $Id: transcode_ext_handler.cc 2010 2009-01-11 19:10:43Z lww $
28
28
*/
29
29
 
30
30
/// \file transcode_ext_handler.cc
60
60
#include "file_io_handler.h"
61
61
#include "transcoding_process_executor.h"
62
62
#include "io_handler_chainer.h"
 
63
#include "play_hook.h"
63
64
 
64
65
#ifdef HAVE_CURL
65
66
    #include "curl_io_handler.h"
66
67
#endif
67
68
 
 
69
#ifdef HAVE_LIBDVDNAV
 
70
    #include "dvd_io_handler.h"
 
71
    #include "metadata/dvd_handler.h"
 
72
    #include "fd_io_handler.h"
 
73
    #include "mpegremux_processor.h"
 
74
#endif
 
75
 
68
76
using namespace zmm;
69
77
 
70
78
TranscodeExternalHandler::TranscodeExternalHandler() : TranscodeHandler()
73
81
 
74
82
Ref<IOHandler> TranscodeExternalHandler::open(Ref<TranscodingProfile> profile, 
75
83
                                              String location, 
76
 
                                              int objectType, 
 
84
                                              Ref<CdsObject> obj, 
77
85
                                              struct File_Info *info)
78
86
{
79
87
    bool isURL = false;
86
94
        throw _Exception(_("Transcoding of file ") + location +
87
95
                           "requested but no profile given");
88
96
    
89
 
    isURL = (IS_CDS_ITEM_INTERNAL_URL(objectType) ||
90
 
            IS_CDS_ITEM_EXTERNAL_URL(objectType));
 
97
    isURL = (IS_CDS_ITEM_INTERNAL_URL(obj->getObjectType()) ||
 
98
            IS_CDS_ITEM_EXTERNAL_URL(obj->getObjectType()));
91
99
 
92
100
    String mimeType = profile->getTargetMimeType();
93
101
 
 
102
    if (IS_CDS_ITEM(obj->getObjectType()))
 
103
    {
 
104
        Ref<CdsItem> it = RefCast(obj, CdsItem);
 
105
        Ref<Dictionary> mappings = ConfigManager::getInstance()->getDictionaryOption(
 
106
                CFG_IMPORT_MAPPINGS_MIMETYPE_TO_CONTENTTYPE_LIST);
 
107
 
 
108
        if (mappings->get(mimeType) == CONTENT_TYPE_PCM)
 
109
        {
 
110
            String freq = it->getResource(0)->getAttribute(MetadataHandler::getResAttrName(R_SAMPLEFREQUENCY));
 
111
            String nrch = it->getResource(0)->getAttribute(MetadataHandler::getResAttrName(R_NRAUDIOCHANNELS));
 
112
 
 
113
            if (string_ok(freq)) 
 
114
                mimeType = mimeType + _(";rate=") + freq;
 
115
            if (string_ok(nrch))
 
116
                mimeType = mimeType + _(";channels=") + nrch;
 
117
        }
 
118
    }
 
119
 
94
120
    info->content_type = ixmlCloneDOMString(mimeType.c_str());
95
121
    
96
122
    info->file_length = UNKNOWN_CONTENT_LENGTH;
 
123
    info->force_chunked = (int)profile->getChunked();
97
124
 
98
125
    Ref<ConfigManager> cfg = ConfigManager::getInstance();
99
126
   
100
 
    String fifo_name = tempName(cfg->getOption(CFG_SERVER_TMPDIR), 
101
 
                                fifo_template);
 
127
    String fifo_name = normalizePath(tempName(cfg->getOption(CFG_SERVER_TMPDIR),
 
128
                                     fifo_template));
102
129
    String arguments;
103
130
    String temp;
104
131
    String command;
105
132
    Ref<Array<StringBase> > arglist;
106
133
    Ref<Array<ProcListItem> > proc_list = nil; 
107
134
 
108
 
    if (isURL && (!profile->acceptURL()))
109
 
    {
 
135
#ifdef SOPCAST
 
136
    service_type_t service = OS_None;
 
137
    if (obj->getFlag(OBJECT_FLAG_ONLINE_SERVICE))
 
138
    {
 
139
        service = (service_type_t)(obj->getAuxData(_(ONLINE_SERVICE_AUX_ID)).toInt());
 
140
    }
 
141
    
 
142
    if (service == OS_SopCast)
 
143
    {
 
144
        Ref<Array<StringBase> > sop_args;
 
145
        int p1 = find_local_port(45000,65500);
 
146
        int p2 = find_local_port(45000,65500);
 
147
        sop_args = parseCommandLine(location + " " + String::from(p1) + " " +
 
148
                   String::from(p2), nil, nil);
 
149
        Ref<ProcessExecutor> spsc(new ProcessExecutor(_("sp-sc-auth"), 
 
150
                                                      sop_args));
 
151
        proc_list = Ref<Array<ProcListItem> >(new Array<ProcListItem>(1));
 
152
        Ref<ProcListItem> pr_item(new ProcListItem(RefCast(spsc, Executor)));
 
153
        proc_list->append(pr_item);
 
154
        location = _("http://localhost:") + String::from(p2) + "/tv.asf";
 
155
#warning check if socket is ready 
 
156
        sleep(15); 
 
157
    }
 
158
#warning check if we can use "accept url" with sopcast
 
159
    else
 
160
    {
 
161
#endif
 
162
        if (isURL && (!profile->acceptURL()))
 
163
        {
110
164
#ifdef HAVE_CURL
111
 
        String url = location;
 
165
            String url = location;
 
166
            strcpy(fifo_template, "mt_transcode_XXXXXX");
 
167
            location = normalizePath(tempName(cfg->getOption(CFG_SERVER_TMPDIR), fifo_template));
 
168
            log_debug("creating reader fifo: %s\n", location.c_str());
 
169
            if (mkfifo(location.c_str(), O_RDWR) == -1)
 
170
            {
 
171
                log_error("Failed to create fifo for the remote content "
 
172
                          "reading thread: %s\n", strerror(errno));
 
173
                throw _Exception(_("Could not create reader fifo!\n"));
 
174
            }
 
175
 
 
176
            try
 
177
            {
 
178
                chmod(location.c_str(), S_IWUSR | S_IRUSR);
 
179
 
 
180
                Ref<IOHandler> c_ioh(new CurlIOHandler(url, NULL, 
 
181
                   cfg->getIntOption(CFG_EXTERNAL_TRANSCODING_CURL_BUFFER_SIZE),
 
182
                   cfg->getIntOption(CFG_EXTERNAL_TRANSCODING_CURL_FILL_SIZE)));
 
183
 
 
184
                Ref<IOHandler> p_ioh(new ProcessIOHandler(location, nil));
 
185
                Ref<Executor> ch(new IOHandlerChainer(c_ioh, p_ioh, 16384));
 
186
                proc_list = Ref<Array<ProcListItem> >(new Array<ProcListItem>(1));
 
187
                Ref<ProcListItem> pr_item(new ProcListItem(ch));
 
188
                proc_list->append(pr_item);
 
189
            }
 
190
            catch (Exception ex)
 
191
            {
 
192
                unlink(location.c_str());
 
193
                throw ex;
 
194
            }
 
195
#else
 
196
            throw _Exception(_("MediaTomb was compiled without libcurl support,"
 
197
                               "data proxying is not available"));
 
198
#endif
 
199
 
 
200
        }
 
201
#ifdef SOPCAST
 
202
    }
 
203
#endif
 
204
 
 
205
#ifdef HAVE_LIBDVDNAV
 
206
    if (obj->getFlag(OBJECT_FLAG_DVD_IMAGE))
 
207
    {
112
208
        strcpy(fifo_template, "mt_transcode_XXXXXX");
113
 
        location = tempName(cfg->getOption(CFG_SERVER_TMPDIR), fifo_template);
 
209
        location = normalizePath(tempName(cfg->getOption(CFG_SERVER_TMPDIR), fifo_template));
114
210
        log_debug("creating reader fifo: %s\n", location.c_str());
115
211
        if (mkfifo(location.c_str(), O_RDWR) == -1)
116
212
        {
117
 
            log_error("Failed to create fifo for the remote content reading thread: %s\n", strerror(errno));
 
213
            log_error("Failed to create fifo for the DVD image "
 
214
                    "reading thread: %s\n", strerror(errno));
118
215
            throw _Exception(_("Could not create reader fifo!\n"));
119
216
        }
120
217
 
 
218
       
121
219
        try
122
220
        {
 
221
            String tmp = obj->getResource(0)->getParameter(DVDHandler::renderKey(DVD_Title));
 
222
            if (!string_ok(tmp))
 
223
                throw _Exception(_("DVD Image requested but title parameter is missing!"));
 
224
            int title = tmp.toInt();
 
225
            if (title < 0)
 
226
                throw _Exception(_("DVD Image - requested invalid title!"));
 
227
 
 
228
            tmp = obj->getResource(0)->getParameter(DVDHandler::renderKey(DVD_Chapter));
 
229
            if (!string_ok(tmp))
 
230
                throw _Exception(_("DVD Image requested but chapter parameter is missing!"));
 
231
            int chapter = tmp.toInt();
 
232
            if (chapter < 0)
 
233
                throw _Exception(_("DVD Image - requested invalid chapter!"));
 
234
 
 
235
            // actually we are retrieving the audio stream id here
 
236
            tmp = obj->getResource(0)->getParameter(DVDHandler::renderKey(DVD_AudioStreamID));
 
237
            if (!string_ok(tmp))
 
238
                throw _Exception(_("DVD Image requested but audio track parameter is missing!"));
 
239
            int audio_track = tmp.toInt();
 
240
            if (audio_track < 0)
 
241
                throw _Exception(_("DVD Image - requested invalid audio stream ID!"));
 
242
 
123
243
            chmod(location.c_str(), S_IWUSR | S_IRUSR);
124
 
 
125
 
            Ref<IOHandler> c_ioh(new CurlIOHandler(url, NULL, 
126
 
                  cfg->getIntOption(CFG_EXTERNAL_TRANSCODING_CURL_BUFFER_SIZE),
127
 
                  cfg->getIntOption(CFG_EXTERNAL_TRANSCODING_CURL_FILL_SIZE)));
128
 
            
 
244
            
 
245
            Ref<IOHandler> dvd_ioh(new DVDIOHandler(obj->getLocation(), title, chapter, audio_track));
 
246
 
 
247
            int from_dvd_fd[2];
 
248
            if (pipe(from_dvd_fd) == -1)
 
249
                throw _Exception(_("Failed to create DVD input pipe!"));
 
250
 
 
251
            int from_remux_fd[2];
 
252
            if (pipe(from_remux_fd) == -1)
 
253
            {
 
254
                close(from_dvd_fd[0]);
 
255
                close(from_dvd_fd[1]);
 
256
                throw _Exception(_("Failed to create remux output pipe!"));
 
257
            }
 
258
 
 
259
            Ref<IOHandler> fd_writer(new FDIOHandler(from_dvd_fd[1]));
 
260
            Ref<Executor> from_dvd(new IOHandlerChainer(dvd_ioh,
 
261
                                                        fd_writer, 16384));
 
262
 
 
263
            Ref<IOHandler> fd_reader(new FDIOHandler(from_remux_fd[0]));
 
264
 
 
265
            Ref<MPEGRemuxProcessor> remux(new MPEGRemuxProcessor(from_dvd_fd[0],
 
266
                                          from_remux_fd[1],
 
267
                                          (unsigned char)audio_track));
 
268
 
 
269
            RefCast(fd_reader, FDIOHandler)->addReference(RefCast(remux, Object));
 
270
            RefCast(fd_reader, FDIOHandler)->addReference(RefCast(from_dvd, Object));
 
271
            RefCast(fd_reader, FDIOHandler)->addReference(RefCast(fd_writer, Object));
 
272
            RefCast(fd_reader, FDIOHandler)->closeOther(fd_writer);
 
273
            
 
274
 
129
275
            Ref<IOHandler> p_ioh(new ProcessIOHandler(location, nil));
130
 
            Ref<Executor> ch(new IOHandlerChainer(c_ioh, p_ioh, 16384));
131
 
            proc_list = Ref<Array<ProcListItem> >(new Array<ProcListItem>(1));
 
276
            Ref<Executor> ch(new IOHandlerChainer(fd_reader, p_ioh, 16384));
 
277
            proc_list = Ref<Array<ProcListItem> >(new Array<ProcListItem>(2));
132
278
            Ref<ProcListItem> pr_item(new ProcListItem(ch));
133
279
            proc_list->append(pr_item);
 
280
            Ref<ProcListItem> pr2_item(new ProcListItem(from_dvd));
 
281
            proc_list->append(pr2_item);
134
282
        }
135
283
        catch (Exception ex)
136
284
        {
137
285
            unlink(location.c_str());
138
286
            throw ex;
139
287
        }
140
 
#else
141
 
        throw _Exception(_("MediaTomb was compiled without libcurl support,"
142
 
                           "data proxying is not available"));
 
288
    }
143
289
#endif
144
290
 
145
 
    }
146
 
 
147
291
    String check;
148
292
    if (profile->getCommand().startsWith(_(_DIR_SEPARATOR)))
149
293
    {
186
330
    {
187
331
        main_proc->removeFile(location);
188
332
    }
189
 
    
 
333
#ifdef HAVE_LIBDVDNAV
 
334
    if (obj->getFlag(OBJECT_FLAG_DVD_IMAGE))
 
335
    {
 
336
        main_proc->removeFile(location);
 
337
    }
 
338
#endif    
190
339
    Ref<IOHandler> io_handler(new BufferedIOHandler(Ref<IOHandler> (new ProcessIOHandler(fifo_name, RefCast(main_proc, Executor), proc_list)), profile->getBufferSize(), profile->getBufferChunkSize(), profile->getBufferInitialFillSize()));
191
340
 
192
341
    io_handler->open(UPNP_READ);
 
342
    PlayHook::getInstance()->trigger(obj);
193
343
    return io_handler;
194
344
}
195
345