~ubuntu-branches/ubuntu/karmic/mpeg4ip/karmic

« back to all changes in this revision

Viewing changes to server/mp4creator/mpeg.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mario Limonciello
  • Date: 2008-01-12 15:59:56 UTC
  • Revision ID: james.westby@ubuntu.com-20080112155956-1vznw5njidvrh649
Tags: upstream-1.6dfsg
ImportĀ upstreamĀ versionĀ 1.6dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * The contents of this file are subject to the Mozilla Public
 
3
 * License Version 1.1 (the "License"); you may not use this file
 
4
 * except in compliance with the License. You may obtain a copy of
 
5
 * the License at http://www.mozilla.org/MPL/
 
6
 * 
 
7
 * Software distributed under the License is distributed on an "AS
 
8
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 
9
 * implied. See the License for the specific language governing
 
10
 * rights and limitations under the License.
 
11
 * 
 
12
 * The Original Code is MPEG4IP.
 
13
 * 
 
14
 * The Initial Developer of the Original Code is Cisco Systems Inc.
 
15
 * Portions created by Cisco Systems Inc. are
 
16
 * Copyright (C) Cisco Systems Inc. 2002.  All Rights Reserved.
 
17
 * 
 
18
 * Contributor(s): 
 
19
 *              Bill May  wmay@cisco.com
 
20
 *              Alix Marchandise-Franquet alix@cisco.com
 
21
 */
 
22
#include "mp4creator.h"
 
23
#include "mpeg2_ps.h"
 
24
 
 
25
static MP4TrackId VideoCreate (MP4FileHandle mp4file, 
 
26
                               mpeg2ps_t *file, 
 
27
                               int vstream,
 
28
                               bool doEncrypt)
 
29
{
 
30
  double frame_rate = mpeg2ps_get_video_stream_framerate(file, vstream);
 
31
  uint8_t video_type;
 
32
  uint16_t w, h;
 
33
  MP4TrackId id;
 
34
  ismacryp_session_id_t ismaCrypSId;
 
35
  mp4v2_ismacrypParams *icPp =  (mp4v2_ismacrypParams *) malloc(sizeof(mp4v2_ismacrypParams));
 
36
  memset(icPp, 0, sizeof(mp4v2_ismacrypParams));
 
37
 
 
38
 
 
39
#ifdef _WIN32
 
40
  MP4Duration mp4FrameDuration;
 
41
  mp4FrameDuration = 
 
42
    (MP4Duration)((double)Mp4TimeScale / frame_rate);
 
43
#else
 
44
  MP4Duration mp4FrameDuration = 
 
45
    (MP4Duration)(Mp4TimeScale / frame_rate);
 
46
#endif
 
47
 
 
48
  h = mpeg2ps_get_video_stream_height(file, vstream);
 
49
  w = mpeg2ps_get_video_stream_width(file, vstream);
 
50
 
 
51
  video_type = mpeg2ps_get_video_stream_mp4_type(file, vstream);
 
52
 
 
53
  if (doEncrypt) {
 
54
    // initialize session
 
55
    if (ismacrypInitSession(&ismaCrypSId,KeyTypeVideo) != 0) {
 
56
      fprintf(stderr, "%s: could not initialize the ISMAcryp session\n",
 
57
              ProgName);
 
58
      return MP4_INVALID_TRACK_ID;
 
59
    }
 
60
    if (ismacrypGetScheme(ismaCrypSId, &(icPp->scheme_type)) != ismacryp_rc_ok) {
 
61
       fprintf(stderr, "%s: could not get ismacryp scheme type. sid %d\n", 
 
62
               ProgName, ismaCrypSId);
 
63
       ismacrypEndSession(ismaCrypSId);
 
64
       return MP4_INVALID_TRACK_ID;
 
65
    }
 
66
    if (ismacrypGetSchemeVersion(ismaCrypSId, &(icPp->scheme_version)) != ismacryp_rc_ok) {
 
67
       fprintf(stderr, "%s: could not get ismacryp scheme ver. sid %d\n",
 
68
               ProgName, ismaCrypSId);
 
69
       ismacrypEndSession(ismaCrypSId);
 
70
       return MP4_INVALID_TRACK_ID;
 
71
    }
 
72
    if (ismacrypGetKMSUri(ismaCrypSId, &(icPp->kms_uri)) != ismacryp_rc_ok) {
 
73
       fprintf(stderr, "%s: could not get ismacryp kms uri. sid %d\n",
 
74
               ProgName, ismaCrypSId);
 
75
       CHECK_AND_FREE(icPp->kms_uri);
 
76
       ismacrypEndSession(ismaCrypSId);
 
77
       return MP4_INVALID_TRACK_ID;
 
78
    }
 
79
    if ( ismacrypGetSelectiveEncryption(ismaCrypSId, &(icPp->selective_enc)) != ismacryp_rc_ok ) {
 
80
       fprintf(stderr, "%s: could not get ismacryp selec enc. sid %d\n",
 
81
               ProgName, ismaCrypSId);
 
82
       ismacrypEndSession(ismaCrypSId);
 
83
       return MP4_INVALID_TRACK_ID;
 
84
    }
 
85
    if (ismacrypGetKeyIndicatorLength(ismaCrypSId, &(icPp->key_ind_len)) != ismacryp_rc_ok) {
 
86
       fprintf(stderr, "%s: could not get ismacryp key ind len. sid %d\n",
 
87
               ProgName, ismaCrypSId);
 
88
       ismacrypEndSession(ismaCrypSId);
 
89
       return MP4_INVALID_TRACK_ID;
 
90
    }
 
91
    if (ismacrypGetIVLength(ismaCrypSId, &(icPp->iv_len)) != ismacryp_rc_ok) {
 
92
       fprintf(stderr, "%s: could not get ismacryp iv len. sid %d\n",
 
93
               ProgName, ismaCrypSId);
 
94
       ismacrypEndSession(ismaCrypSId);
 
95
       return MP4_INVALID_TRACK_ID;
 
96
    }
 
97
    id = MP4AddEncVideoTrack(mp4file, 
 
98
                             Mp4TimeScale, 
 
99
                             mp4FrameDuration,
 
100
                             w, 
 
101
                             h,
 
102
                             icPp,
 
103
                             video_type);
 
104
  } else {
 
105
    id = MP4AddVideoTrack(mp4file, 
 
106
                          Mp4TimeScale, 
 
107
                          mp4FrameDuration,
 
108
                          w, 
 
109
                          h, 
 
110
                          video_type);
 
111
  }
 
112
 
 
113
  //printf("duration "U64" w %d h %d type %x\n", mp4FrameDuration, w, h, video_type);
 
114
  if (MP4GetNumberOfTracks(mp4file, MP4_VIDEO_TRACK_TYPE) == 1) {
 
115
    MP4SetVideoProfileLevel(mp4file, 0xfe); // undefined profile
 
116
  }
 
117
 
 
118
  if (id == MP4_INVALID_TRACK_ID) {
 
119
    fprintf(stderr, "%s:Couldn't add video track %d", ProgName, vstream);
 
120
    return MP4_INVALID_TRACK_ID;
 
121
  }
 
122
  uint8_t *buf;
 
123
  uint32_t blen;
 
124
  uint32_t frames = 1;
 
125
#if 0
 
126
  printf("Processing %lu video frames\n", frames_max);
 
127
#endif
 
128
  uint32_t refFrame = 1;
 
129
  uint8_t frame_type;
 
130
  while (mpeg2ps_get_video_frame(file, 
 
131
                                 vstream,
 
132
                                 &buf, 
 
133
                                 &blen, 
 
134
                                 &frame_type,
 
135
                                 TS_90000,
 
136
                                 NULL)) {
 
137
    if (buf[blen - 4] == 0 &&
 
138
        buf[blen - 3] == 0 &&
 
139
        buf[blen - 2] == 1) blen -= 4;
 
140
    
 
141
    // encrypt the sample if neeed
 
142
    if (doEncrypt) {
 
143
      u_int8_t* encSampleData = NULL;
 
144
      u_int32_t encSampleLen = 0;
 
145
      if (ismacrypEncryptSampleAddHeader(ismaCrypSId, blen, buf,
 
146
                                &encSampleLen, &encSampleData) != 0) {
 
147
        fprintf(stderr, 
 
148
                "%s: can't encrypt video sample and add header %u\n", ProgName, id);
 
149
      }
 
150
      MP4WriteSample(mp4file, id, encSampleData, encSampleLen, 
 
151
                     mp4FrameDuration, 0, 
 
152
                     frame_type == 1 ? true : false);
 
153
      if (encSampleData != NULL) {
 
154
        free(encSampleData);
 
155
      }
 
156
    } else {
 
157
      MP4WriteSample(mp4file, id, buf, blen, mp4FrameDuration, 0, 
 
158
                     frame_type == 1 ? true : false);
 
159
#if 0
 
160
      printf("frame %d len %d duration "U64" ftype %d\n",
 
161
             frames, blen, mp4FrameDuration, frame_type);
 
162
#endif
 
163
    }
 
164
    if (frame_type != 3) {
 
165
      // I or P frame
 
166
      MP4SetSampleRenderingOffset(mp4file, id, refFrame, 
 
167
                                  (frames - refFrame) * mp4FrameDuration);
 
168
      refFrame = frames;
 
169
    }
 
170
    frames++;
 
171
#if 0
 
172
    if ((frames % 100) == 0) printf("%d frames\n", frames);
 
173
#endif
 
174
  }
 
175
 
 
176
  // if encrypting, terminate the ismacryp session
 
177
  if (doEncrypt) {
 
178
    if (ismacrypEndSession(ismaCrypSId) != 0) {
 
179
      fprintf(stderr, 
 
180
              "%s: could not end the ISMAcryp session\n",
 
181
              ProgName);
 
182
      return MP4_INVALID_TRACK_ID;
 
183
    }
 
184
  }
 
185
  return id;
 
186
}
 
187
 
 
188
static MP4TrackId AudioCreate (MP4FileHandle mp4file, 
 
189
                               mpeg2ps_t *file, 
 
190
                               int astream,
 
191
                               bool doEncrypt)
 
192
{
 
193
  uint16_t freq;
 
194
  int type;
 
195
  MP4TrackId id;
 
196
  uint16_t samples_per_frame;
 
197
  uint8_t *buf = NULL;
 
198
  uint32_t blen = 0;
 
199
  uint32_t frame_num = 1;
 
200
  ismacryp_session_id_t ismaCrypSId;
 
201
  mp4v2_ismacrypParams *icPp =  (mp4v2_ismacrypParams *) malloc(sizeof(mp4v2_ismacrypParams));
 
202
  MP4AV_Mp3Header hdr;
 
203
  u_int8_t mpegVersion;
 
204
  memset(icPp, 0, sizeof(mp4v2_ismacrypParams));
 
205
 
 
206
  type = mpeg2ps_get_audio_stream_type(file, astream);
 
207
 
 
208
  if (type != MPEG_AUDIO_MPEG) {
 
209
    fprintf(stderr, "Unsupported audio format %d in audio stream %d\n", 
 
210
            type, astream);
 
211
    return MP4_INVALID_TRACK_ID;
 
212
  }
 
213
 
 
214
  freq = mpeg2ps_get_audio_stream_sample_freq(file, astream);
 
215
 
 
216
  if (mpeg2ps_get_audio_frame(file, 
 
217
                              astream,
 
218
                              &buf, 
 
219
                              &blen,
 
220
                              TS_90000,
 
221
                              NULL, 
 
222
                              NULL) == false) {
 
223
    fprintf(stderr, "No audio tracks in audio stream %d\n", astream);
 
224
    return MP4_INVALID_TRACK_ID;
 
225
  }
 
226
  
 
227
  hdr = MP4AV_Mp3HeaderFromBytes(buf);
 
228
  mpegVersion = MP4AV_Mp3GetHdrVersion(hdr);
 
229
  samples_per_frame = MP4AV_Mp3GetHdrSamplingWindow(hdr);
 
230
 
 
231
  u_int8_t audioType = MP4AV_Mp3ToMp4AudioType(mpegVersion);
 
232
  
 
233
  if (audioType == MP4_INVALID_AUDIO_TYPE
 
234
      || samples_per_frame == 0) {
 
235
    fprintf(stderr,     
 
236
            "%s: data in file doesn't appear to be valid audio\n",
 
237
            ProgName);
 
238
    return MP4_INVALID_TRACK_ID;
 
239
  }
 
240
 
 
241
  MP4Duration duration = (90000 * samples_per_frame) / freq;
 
242
 
 
243
  if (doEncrypt) {
 
244
    // initialize the ismacryp session
 
245
    if (ismacrypInitSession(&ismaCrypSId,KeyTypeAudio) != 0) {
 
246
      fprintf(stderr, 
 
247
              "%s: could not initialize the ISMAcryp session\n",
 
248
              ProgName);
 
249
      return MP4_INVALID_TRACK_ID;
 
250
    }
 
251
    if (ismacrypGetScheme(ismaCrypSId, &(icPp->scheme_type)) != ismacryp_rc_ok) {
 
252
       fprintf(stderr, "%s: could not get ismacryp scheme type. sid %d\n", 
 
253
               ProgName, ismaCrypSId);
 
254
       ismacrypEndSession(ismaCrypSId);
 
255
       return MP4_INVALID_TRACK_ID;
 
256
    }
 
257
    if (ismacrypGetSchemeVersion(ismaCrypSId, &(icPp->scheme_version)) != ismacryp_rc_ok) {
 
258
       fprintf(stderr, "%s: could not get ismacryp scheme ver. sid %d\n",
 
259
               ProgName, ismaCrypSId);
 
260
       ismacrypEndSession(ismaCrypSId);
 
261
       return MP4_INVALID_TRACK_ID;
 
262
    }
 
263
    if (ismacrypGetKMSUri(ismaCrypSId, &(icPp->kms_uri)) != ismacryp_rc_ok) {
 
264
       fprintf(stderr, "%s: could not get ismacryp kms uri. sid %d\n",
 
265
               ProgName, ismaCrypSId);
 
266
       CHECK_AND_FREE(icPp->kms_uri);
 
267
       ismacrypEndSession(ismaCrypSId);
 
268
       return MP4_INVALID_TRACK_ID;
 
269
    }
 
270
    if ( ismacrypGetSelectiveEncryption(ismaCrypSId, &(icPp->selective_enc)) != ismacryp_rc_ok ) {
 
271
       fprintf(stderr, "%s: could not get ismacryp selec enc. sid %d\n",
 
272
               ProgName, ismaCrypSId);
 
273
       ismacrypEndSession(ismaCrypSId);
 
274
       return MP4_INVALID_TRACK_ID;
 
275
    }
 
276
    if (ismacrypGetKeyIndicatorLength(ismaCrypSId, &(icPp->key_ind_len)) != ismacryp_rc_ok) {
 
277
       fprintf(stderr, "%s: could not get ismacryp key ind len. sid %d\n",
 
278
               ProgName, ismaCrypSId);
 
279
       ismacrypEndSession(ismaCrypSId);
 
280
       return MP4_INVALID_TRACK_ID;
 
281
    }
 
282
    if (ismacrypGetIVLength(ismaCrypSId, &(icPp->iv_len)) != ismacryp_rc_ok) {
 
283
       fprintf(stderr, "%s: could not get ismacryp iv len. sid %d\n",
 
284
               ProgName, ismaCrypSId);
 
285
       ismacrypEndSession(ismaCrypSId);
 
286
       return MP4_INVALID_TRACK_ID;
 
287
    }
 
288
    id = MP4AddEncAudioTrack(mp4file, 
 
289
                             90000, 
 
290
                             duration,
 
291
                             icPp,
 
292
                             audioType);
 
293
  } else {
 
294
    id = MP4AddAudioTrack(mp4file, 
 
295
                          90000, 
 
296
                          duration,
 
297
                          audioType);
 
298
  }
 
299
  
 
300
  if (id == MP4_INVALID_TRACK_ID) {
 
301
    fprintf(stderr, 
 
302
            "%s: can't create audio track from stream %d\n", 
 
303
            ProgName, astream);
 
304
    return MP4_INVALID_TRACK_ID;
 
305
  }
 
306
 
 
307
  if (MP4GetNumberOfTracks(mp4file, MP4_AUDIO_TRACK_TYPE) == 1) {
 
308
    MP4SetAudioProfileLevel(mp4file, 0xFE);
 
309
  }
 
310
 
 
311
  do {
 
312
    // encrypt if needed
 
313
     if (doEncrypt) {
 
314
       u_int8_t* encSampleData = NULL;
 
315
       u_int32_t encSampleLen = 0;
 
316
       if (ismacrypEncryptSampleAddHeader(ismaCrypSId, blen, buf,
 
317
                                          &encSampleLen, &encSampleData) != 0) {
 
318
         fprintf(stderr,        
 
319
                 "%s: can't encrypt audio sample and add header %u\n", ProgName, id);
 
320
       }
 
321
       // now write the sample
 
322
       if (!MP4WriteSample(mp4file, id, encSampleData, encSampleLen)) {
 
323
         fprintf(stderr, "%s: can't write audio track %u, stream %d",
 
324
                 ProgName, frame_num, astream);
 
325
         MP4DeleteTrack(mp4file, id);
 
326
         return MP4_INVALID_TRACK_ID;
 
327
       }
 
328
       if (encSampleData != NULL) {
 
329
         free(encSampleData);
 
330
       }
 
331
    }
 
332
     // now write the sample
 
333
    if (!MP4WriteSample(mp4file, id, buf, blen)) {
 
334
      fprintf(stderr, "%s: can't write audio track %u, stream %d",
 
335
              ProgName, frame_num, astream);
 
336
      MP4DeleteTrack(mp4file, id);
 
337
      return MP4_INVALID_TRACK_ID;
 
338
    }
 
339
    frame_num++;
 
340
#if 0
 
341
    if ((frame_num % 100) == 0) printf("Audio frame %d\n", frame_num);
 
342
#endif
 
343
  }  while (mpeg2ps_get_audio_frame(file, 
 
344
                                    astream, 
 
345
                                    &buf, 
 
346
                                    &blen,
 
347
                                    TS_90000,
 
348
                                    NULL, NULL));
 
349
  
 
350
  // if encrypting, terminate the ismacryp session
 
351
  if (doEncrypt) {
 
352
    if (ismacrypEndSession(ismaCrypSId) != 0) {
 
353
      fprintf(stderr, 
 
354
              "%s: could not end the ISMAcryp session\n",
 
355
              ProgName);
 
356
      return MP4_INVALID_TRACK_ID;
 
357
    }
 
358
  }
 
359
 
 
360
  return id;
 
361
}
 
362
 
 
363
MP4TrackId *MpegCreator (MP4FileHandle mp4file, const char *fname, bool doEncrypt)
 
364
{
 
365
 
 
366
  mpeg2ps_t *file;
 
367
  int video_streams, audio_streams;
 
368
  int ix;
 
369
  MP4TrackId *pTrackId;
 
370
 
 
371
  file = mpeg2ps_init(fname);
 
372
  video_streams = mpeg2ps_get_video_stream_count(file);
 
373
  audio_streams = mpeg2ps_get_audio_stream_count(file);
 
374
 
 
375
  pTrackId = 
 
376
    (MP4TrackId *)malloc(sizeof(MP4TrackId) * (audio_streams + video_streams + 1));
 
377
 
 
378
  for (ix = 0; ix < video_streams + audio_streams + 1; ix++) {
 
379
    pTrackId[ix] = MP4_INVALID_TRACK_ID;
 
380
  }
 
381
 
 
382
  for (ix = 0; ix < video_streams; ix++) {
 
383
    pTrackId[ix] = VideoCreate(mp4file, file, ix, doEncrypt);
 
384
  }
 
385
  for (ix = 0; ix < audio_streams; ix++) {
 
386
    pTrackId[ix + video_streams] = AudioCreate(mp4file, file, ix, doEncrypt);
 
387
  }
 
388
  return pTrackId;
 
389
}