| | 210 | ComponentResult DescExt_XiphTheora(KaxTrackEntry *tr_entry, SampleDescriptionHandle desc, DescExtDirection dir) |
|---|
| | 211 | { |
|---|
| | 212 | if (!tr_entry || !desc) return paramErr; |
|---|
| | 213 | ImageDescriptionHandle imgDesc = (ImageDescriptionHandle) desc; |
|---|
| | 214 | |
|---|
| | 215 | if (dir == kToSampleDescription) { |
|---|
| | 216 | Handle imgDescExt = NewHandle(0); |
|---|
| | 217 | unsigned char *privateBuf; |
|---|
| | 218 | int i; |
|---|
| | 219 | int numPackets; |
|---|
| | 220 | int *packetSizes; |
|---|
| | 221 | int offset = 1; |
|---|
| | 222 | UInt32 uid = 0; |
|---|
| | 223 | |
|---|
| | 224 | KaxCodecPrivate *codecPrivate = FindChild<KaxCodecPrivate>(*tr_entry); |
|---|
| | 225 | if (codecPrivate == NULL) |
|---|
| | 226 | return invalidAtomErr; |
|---|
| | 227 | |
|---|
| | 228 | KaxTrackUID *trackUID = FindChild<KaxTrackUID>(*tr_entry); |
|---|
| | 229 | if (trackUID != NULL) |
|---|
| | 230 | uid = uint32(*trackUID); |
|---|
| | 231 | |
|---|
| | 232 | privateBuf = (unsigned char *) codecPrivate->GetBuffer(); |
|---|
| | 233 | numPackets = privateBuf[0] + 1; |
|---|
| | 234 | packetSizes = (int *) NewPtrClear(sizeof(int) * numPackets); |
|---|
| | 235 | |
|---|
| | 236 | // get the sizes of the packets |
|---|
| | 237 | packetSizes[numPackets - 1] = codecPrivate->GetSize() - 1; |
|---|
| | 238 | int packetNum = 0; |
|---|
| | 239 | for (i = 1; packetNum < numPackets - 1; i++) { |
|---|
| | 240 | packetSizes[packetNum] += privateBuf[i]; |
|---|
| | 241 | if (privateBuf[i] < 255) { |
|---|
| | 242 | packetSizes[numPackets - 1] -= packetSizes[packetNum]; |
|---|
| | 243 | packetNum++; |
|---|
| | 244 | } |
|---|
| | 245 | offset++; |
|---|
| | 246 | } |
|---|
| | 247 | |
|---|
| | 248 | // first packet |
|---|
| | 249 | unsigned long serialnoatom[3] = { EndianU32_NtoB(sizeof(serialnoatom)), |
|---|
| | 250 | EndianU32_NtoB(kCookieTypeOggSerialNo), EndianU32_NtoB(uid) }; |
|---|
| | 251 | unsigned long atomhead[2] = { EndianU32_NtoB(packetSizes[0] + sizeof(atomhead)), |
|---|
| | 252 | EndianU32_NtoB(kCookieTypeTheoraHeader) }; |
|---|
| | 253 | |
|---|
| | 254 | PtrAndHand(serialnoatom, imgDescExt, sizeof(serialnoatom)); //check errors? |
|---|
| | 255 | PtrAndHand(atomhead, imgDescExt, sizeof(atomhead)); //check errors? |
|---|
| | 256 | PtrAndHand(&privateBuf[offset], imgDescExt, packetSizes[0]); |
|---|
| | 257 | |
|---|
| | 258 | // second packet |
|---|
| | 259 | unsigned long atomhead2[2] = { EndianU32_NtoB(packetSizes[1] + sizeof(atomhead)), |
|---|
| | 260 | EndianU32_NtoB(kCookieTypeTheoraComments) }; |
|---|
| | 261 | PtrAndHand(atomhead2, imgDescExt, sizeof(atomhead2)); |
|---|
| | 262 | PtrAndHand(&privateBuf[offset + packetSizes[0]], imgDescExt, packetSizes[1]); |
|---|
| | 263 | |
|---|
| | 264 | // third packet |
|---|
| | 265 | unsigned long atomhead3[2] = { EndianU32_NtoB(packetSizes[2] + sizeof(atomhead)), |
|---|
| | 266 | EndianU32_NtoB(kCookieTypeTheoraCodebooks) }; |
|---|
| | 267 | PtrAndHand(atomhead3, imgDescExt, sizeof(atomhead3)); |
|---|
| | 268 | PtrAndHand(&privateBuf[offset + packetSizes[1] + packetSizes[0]], imgDescExt, packetSizes[2]); |
|---|
| | 269 | |
|---|
| | 270 | // add the extension |
|---|
| | 271 | unsigned long endAtom[2] = { EndianU32_NtoB(sizeof(endAtom)), EndianU32_NtoB(kAudioTerminatorAtomType) }; |
|---|
| | 272 | PtrAndHand(endAtom, imgDescExt, sizeof(endAtom)); |
|---|
| | 273 | |
|---|
| | 274 | AddImageDescriptionExtension(imgDesc, imgDescExt, kSampleDescriptionExtensionTheora); |
|---|
| | 275 | |
|---|
| | 276 | DisposePtr((Ptr)packetSizes); |
|---|
| | 277 | DisposeHandle(imgDescExt); |
|---|
| | 278 | } |
|---|
| | 279 | return noErr; |
|---|
| | 280 | } |
|---|
| | 281 | |
|---|
| 481 | | #if 0 |
|---|
| 482 | | } else if (codecString == MKV_V_THEORA) { |
|---|
| 483 | | // we need 3 setup packets for the image description extension, but |
|---|
| 484 | | // the sample files I muxed have only 2 packets in the Codec Private element. |
|---|
| 485 | | // Despite the Matroska specs agreeing with me about the 3 packets. |
|---|
| 486 | | // Will figure out later. |
|---|
| 487 | | } else if (codecString.compare(0, strlen(MKV_A_AAC), string(MKV_A_AAC)) == 0) { |
|---|
| 488 | | // esds extension gives us the channel mapping for AAC |
|---|
| 489 | | SoundDescriptionHandle sndDesc = (SoundDescriptionHandle) desc; |
|---|
| 490 | | |
|---|
| 491 | | KaxCodecPrivate *codecPrivate = FindChild<KaxCodecPrivate>(*tr_entry); |
|---|
| 492 | | if (codecPrivate == NULL) |
|---|
| 493 | | return; |
|---|
| 494 | | |
|---|
| 495 | | Handle sndDescExt = NewHandle(codecPrivate->GetSize()); |
|---|
| 496 | | memcpy(*sndDescExt, codecPrivate->GetBuffer(), codecPrivate->GetSize()); |
|---|
| 497 | | |
|---|
| 498 | | AddSoundDescriptionExtension(sndDesc, sndDescExt, 'esds'); |
|---|
| 499 | | |
|---|
| 500 | | DisposeHandle((Handle) sndDescExt); |
|---|
| 501 | | #endif |
|---|
| | 553 | |
|---|