[haiku-commits] r34354 - in haiku/trunk/src/add-ons/media/plugins/avi_reader: . libOpenDML

  • From: dlmcpaul@xxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 29 Nov 2009 22:07:36 +0100 (CET)

Author: dlmcpaul
Date: 2009-11-29 22:07:35 +0100 (Sun, 29 Nov 2009)
New Revision: 34354
Changeset: http://dev.haiku-os.org/changeset/34354/haiku

Modified:
   haiku/trunk/src/add-ons/media/plugins/avi_reader/avi_reader.cpp
   haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp
   haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.cpp
   haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h
   haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp
   haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h
   haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp
   haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h
Log:
Added ODML Index support, still needs work though too much duplicated code.  
Feedback welcome

Modified: haiku/trunk/src/add-ons/media/plugins/avi_reader/avi_reader.cpp
===================================================================
--- haiku/trunk/src/add-ons/media/plugins/avi_reader/avi_reader.cpp     
2009-11-29 20:51:12 UTC (rev 34353)
+++ haiku/trunk/src/add-ons/media/plugins/avi_reader/avi_reader.cpp     
2009-11-29 21:07:35 UTC (rev 34354)
@@ -445,33 +445,36 @@
        mediaHeader->start_time = (cookie->frame_pos * 1000000LL
                * cookie->frames_per_sec_scale) / cookie->frames_per_sec_rate;
        
-       TRACE("stream %d (%s): start_time %.6f, pos %.3f %%, frame %Ld chunk 
size %ld\n", 
+       TRACE("stream %d (%s): start_time %.6f, pos %.3f %%, frame %Ld chunk 
size %ld offset %Ld\n", 
                cookie->stream, cookie->is_audio ? "A" : cookie->is_video ? "V" 
: "?", 
                mediaHeader->start_time / 1000000.0, cookie->frame_pos * 100.0
-               / cookie->frame_count, cookie->frame_pos, size);
+               / cookie->frame_count, cookie->frame_pos, size, start);
 
        if (cookie->is_audio) {
                mediaHeader->type = B_MEDIA_ENCODED_AUDIO;
                mediaHeader->u.encoded_audio.buffer_flags = keyframe ?
                        B_MEDIA_KEY_FRAME : 0;
 
-               cookie->frame_pos += (uint64)(ceil((double)size / 
(double)cookie->frame_size)) * cookie->frames_per_sec_scale;
                cookie->byte_pos += size;
                // frame_pos is sample no for vbr encoded audio and byte 
position for everything else
-//             if (cookie->is_vbr) {
+               if (cookie->is_vbr) {
                        // advance by frame_size
-//             } else {
+                       cookie->frame_pos += cookie->frame_size;
+               } else {
+                       cookie->frame_pos += (uint64)(ceil((double)size / 
(double)cookie->frame_size)) * cookie->frames_per_sec_scale;
 //                     cookie->frame_pos += (uint64)(ceil((double)size / 
(double)cookie->frame_size)) * cookie->frames_per_sec / 
cookie->avg_bytes_per_sec;
                        // advance by bytes in chunk and calculate frame_pos
 //                     time = cookie->byte_pos * 1000000LL / 
cookie->bytes_per_second;
 //                     cookie->frame_pos = time * cookie->frames_per_sec_rate 
/ cookie->frames_per_sec_scale / 1000000LL;
-//             }
+               }
        } else if (cookie->is_video) {
                mediaHeader->type = B_MEDIA_ENCODED_VIDEO;
-               mediaHeader->u.encoded_video.field_flags = keyframe ?
+               mediaHeader->u.encoded_video.field_flags = keyframe ? 
                        B_MEDIA_KEY_FRAME : 0;
                mediaHeader->u.encoded_video.first_active_line = 0;
                mediaHeader->u.encoded_video.line_count = cookie->line_count;
+               mediaHeader->u.encoded_video.field_number = 0;
+               mediaHeader->u.encoded_video.field_sequence = cookie->frame_pos;
                cookie->frame_pos += cookie->frame_size;
        } else {
                return B_BAD_VALUE;

Modified: 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp
===================================================================
--- 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp   
    2009-11-29 20:51:12 UTC (rev 34353)
+++ 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/FallbackIndex.cpp   
    2009-11-29 21:07:35 UTC (rev 34354)
@@ -26,7 +26,6 @@
 #include <math.h>
 #include <stdio.h>
 #include "FallbackIndex.h"
-#include "OpenDMLParser.h"
 
 //#define TRACE_START_INDEX
 #ifdef TRACE_START_INDEX

Modified: haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.cpp
===================================================================
--- haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.cpp       
2009-11-29 20:51:12 UTC (rev 34353)
+++ haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.cpp       
2009-11-29 21:07:35 UTC (rev 34354)
@@ -26,7 +26,6 @@
 #include <stdio.h>
 #include "ReaderPlugin.h" // B_MEDIA_*
 #include "Index.h"
-#include "OpenDMLParser.h"
 
 //#define TRACE_INDEX
 #ifdef TRACE_INDEX
@@ -129,7 +128,7 @@
                        if (data->seek_index[i].keyframe) {
                                lastKeyframePos = pos;
                                lastKeyframeIndex = i;
-                               TRACE("keyframe at index %ld, frame %ld (seek: 
%ld)\n", i,
+                               TRACE("keyframe at index %ld, frame %Ld (seek: 
%Ld)\n", i,
                                        pos, frame_pos);
                        }
 
@@ -169,7 +168,7 @@
        return B_ERROR;
 
 done:
-       TRACE("seek done: index: pos %d\n", data->current_chunk);
+       TRACE("seek done: index: pos %Ld\n", data->current_chunk);
        // recalculate frame and time after seek
        *frame = frame_pos;
        *time = (frame_pos * 1000000LL * stream->frames_per_sec_scale)
@@ -199,7 +198,7 @@
        IndexEntry _index;
        for (uint32 i = 0; i < fStreamData[stream_index].seek_index_next; i++) {
                _index = fStreamData[stream_index].seek_index[i];
-               printf("Frame %Ld, pos %Ld, size %ld, pts 
%Ld\n",_index.frame_no, _index.position, _index.size, _index.pts);
+               printf("index %ld Frame %Ld, pos %Ld, size %ld, pts 
%Ld\n",i,_index.frame_no, _index.position, _index.size, _index.pts);
        }
 }
 

Modified: haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h
===================================================================
--- haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h 
2009-11-29 20:51:12 UTC (rev 34353)
+++ haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/Index.h 
2009-11-29 21:07:35 UTC (rev 34354)
@@ -28,6 +28,8 @@
 #include <SupportDefs.h>
 #include <vector>
 
+#include "OpenDMLParser.h"
+
 /*
        This class handles all indexing of an AVI file
        Subclasses should override Init and create index entries based on the

Modified: 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp
===================================================================
--- 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp    
    2009-11-29 20:51:12 UTC (rev 34353)
+++ 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.cpp    
    2009-11-29 21:07:35 UTC (rev 34354)
@@ -23,10 +23,21 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <SupportDefs.h>
+#include <math.h>
 #include <stdio.h>
+
 #include "OpenDMLIndex.h"
 
+//#define TRACE_START_INDEX
+#ifdef TRACE_START_INDEX
+  #define TRACE printf
+#else
+  #define TRACE(a...)
+#endif
 
+#define ERROR(a...) fprintf(stderr, a)
+
+
 OpenDMLIndex::OpenDMLIndex(BPositionIO *source, OpenDMLParser *parser)
  :     Index(source, parser)
 {
@@ -41,5 +52,149 @@
 status_t
 OpenDMLIndex::Init()
 {
-       return B_ERROR;
+       TRACE("Constructing a OpenDML Index\n");
+
+       uint32 lastFrame;
+       bigtime_t pts;
+       odml_index_header superIndex;
+       const OpenDMLStream *stream;
+       
+       int64 pos = 0;
+       uint32 bytesRead;       
+
+       for (uint32 i=0; i < fStreamCount; i++) {
+               stream = fParser->StreamInfo(i);
+
+               pos = stream->odml_index_start;
+               bytesRead = sizeof(odml_index_header);
+
+               if ((int32)bytesRead != fSource->ReadAt(pos, &superIndex, 
bytesRead)) {
+                       ERROR("libOpenDML: OpenDMLIndex::Init file reading 
failed to read superindex\n");
+                       return B_IO_ERROR;
+               }
+               
+               pos += bytesRead;
+               
+               pts = 0;
+               lastFrame = 0;
+               
+               ReadIndex(i, pos, &lastFrame, &pts, &superIndex);
+       }
+
+       return B_OK;
 }
+
+status_t
+OpenDMLIndex::ReadIndex(uint32 stream_index, int64 pos, uint32 *lastFrame, 
bigtime_t *pts, odml_index_header *superIndex) {
+
+odml_superindex_entry superIndexEntry;
+//odml_field_index_entry fieldIndexEntry;
+uint32 bytesRead;
+
+const OpenDMLStream *stream = fParser->StreamInfo(stream_index);
+       
+       for (uint32 i=0; i < superIndex->entries_used; i++) {
+                       
+               if (superIndex->index_type == AVI_INDEX_OF_INDEXES) {
+                       
+                       bytesRead = sizeof(odml_superindex_entry);
+       
+                       if ((int32)bytesRead != fSource->ReadAt(pos, 
&superIndexEntry, bytesRead)) {
+                               ERROR("libOpenDML: OpenDMLIndex::Init file 
reading failed to read superindex entry\n");
+                               return B_IO_ERROR;
+                       }
+                       
+                       pos += bytesRead;
+                       
+                       if (superIndexEntry.start == 0) {
+                               continue;
+                       }
+                       
+                       if (superIndex->index_sub_type == AVI_INDEX_2FIELD) {
+                       } else {
+                               ReadChunkIndex(stream_index, 
superIndexEntry.start + 8, lastFrame, pts, stream);
+                       }
+               }
+       }
+       
+       return B_OK;
+}
+
+status_t
+OpenDMLIndex::ReadChunkIndex(uint32 stream_index, int64 pos, uint32 
*lastFrame, bigtime_t *pts, const OpenDMLStream *stream) {
+       
+odml_index_entry chunkIndexEntry;
+odml_chunk_index_header chunkIndex;
+uint32 bytesRead;
+uint32 frameNo;
+bool keyframe;
+uint32 sample_size;
+int64 position;
+uint32 size;
+
+       bytesRead = sizeof(odml_chunk_index_header);
+               
+       if ((int32)bytesRead != fSource->ReadAt(pos, &chunkIndex, bytesRead)) {
+               ERROR("libOpenDML: OpenDMLIndex::Init file reading failed to 
read Chunk Index\n");
+               return B_IO_ERROR;
+       }
+       
+       pos += bytesRead;
+
+       for (uint32 i=0; i<chunkIndex.entries_used; i++) {
+               bytesRead = sizeof(odml_index_entry);
+                                       
+               if ((int32)bytesRead != fSource->ReadAt(pos, &chunkIndexEntry, 
bytesRead)) {
+                       ERROR("libOpenDML: OpenDMLIndex::Init file reading 
failed to read Chunk Index Entry\n");
+                       return B_IO_ERROR;
+               }
+                               
+               pos += bytesRead;
+                                       
+               keyframe = (chunkIndexEntry.size & 0x80000000) ? false : true;
+               position = chunkIndex.base_offset + chunkIndexEntry.start - 8;
+               size = chunkIndexEntry.size & 0x7fffffff;
+               frameNo = *lastFrame;
+                                       
+               if (stream->is_video) {
+                       // Video is easy enough, it is always 1 frame = 1 index
+                       *pts = *lastFrame * 1000000LL * 
stream->frames_per_sec_scale / stream->frames_per_sec_rate;
+                       (*lastFrame)++;
+               } else if (stream->is_audio) {
+
+                       *pts = *lastFrame * 1000000LL / 
stream->audio_format->frames_per_sec;
+
+                       // Audio varies based on many different hacks over the 
years
+                       // The simplest is chunk size / sample size = no of 
samples in the chunk for uncompressed audio
+                       // ABR Compressed audio is more difficult and VBR 
Compressed audio is even harder
+                       // What follows is what I have worked out from various 
sources across the internet.
+                       if (stream->audio_format->format_tag != 0x0001) {
+                               // VBR audio is detected as having a 
block_align >= 960
+                               if (stream->audio_format->block_align >= 960) {
+                                       // VBR Audio so block_align is the 
largest no of samples in a chunk
+                                       // scale is the no of samples in a frame
+                                       // rate is the sample rate
+                                       // but we must round up when 
calculating no of frames in a chunk
+                                       *lastFrame += 
(uint64)(ceil((double)size / (double)stream->audio_format->block_align)) * 
stream->frames_per_sec_scale;
+                               } else {
+                                       // ABR Audio so use Chunk Size and 
average bytes per second to determine how many samples there are in the chunk
+                                       *lastFrame += 
(uint64)(ceil((double)size / (double)stream->audio_format->block_align)) * 
stream->audio_format->frames_per_sec / stream->audio_format->avg_bytes_per_sec;
+                               }
+                       } else {
+                               // sample size can be corrupt
+                               if (stream->stream_header.sample_size > 0) {
+                                       sample_size = 
stream->stream_header.sample_size;
+                               } else {
+                                       // compute sample size
+                                       sample_size = 
stream->audio_format->bits_per_sample * stream->audio_format->channels / 8;
+                               }
+                               *lastFrame += size / 
stream->stream_header.sample_size;
+                       }
+               }
+                       
+               AddIndex(stream_index, position, size, frameNo, *pts, keyframe);
+       }
+       
+       return B_OK;
+}
+

Modified: 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h
===================================================================
--- haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h  
2009-11-29 20:51:12 UTC (rev 34353)
+++ haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/OpenDMLIndex.h  
2009-11-29 21:07:35 UTC (rev 34354)
@@ -34,6 +34,9 @@
                                                ~OpenDMLIndex();
 
        status_t                        Init();
+private:
+       status_t                        ReadIndex(uint32 stream_index, int64 
pos, uint32 *lastFrame, bigtime_t *pts, odml_index_header *superIndex);
+       status_t                        ReadChunkIndex(uint32 stream_index, 
int64 pos, uint32 *lastFrame, bigtime_t *pts, const OpenDMLStream *stream);
 };
 
 #endif

Modified: 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp
===================================================================
--- 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp   
    2009-11-29 20:51:12 UTC (rev 34353)
+++ 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.cpp   
    2009-11-29 21:07:35 UTC (rev 34354)
@@ -28,8 +28,8 @@
 #include <math.h>
 #include <stdio.h>
 #include <new>
+
 #include "StandardIndex.h"
-#include "OpenDMLParser.h"
 
 
 //#define TRACE_START_INDEX
@@ -95,7 +95,7 @@
        }
 
        int stream_index;
-       off_t position;
+       int64 position;
        uint32 size;
        uint64 frame[fStreamCount];
        uint64 frame_no;
@@ -111,11 +111,21 @@
 
        for (uint32 i = 0; i < fIndexSize; i++) {
                
+               if (fIndex[i].chunk_id == 0) {
+                       printf("Corrupt Index entry at %ld/%ld\n",i,fIndexSize);
+                       continue;
+               }
+                               
                stream_index = ((fIndex[i].chunk_id & 0xff) - '0') * 10;
-        stream_index += ((fIndex[i].chunk_id >> 8) & 0xff) - '0';
+               stream_index += ((fIndex[i].chunk_id >> 8) & 0xff) - '0';
 
                stream = fParser->StreamInfo(stream_index);
         
+               if (stream == NULL) {
+                       printf("No Stream Info for stream %d\n",stream_index);
+                       continue;
+               }
+        
         keyframe = (fIndex[i].flags >> AVIIF_KEYFRAME_SHIFT) & 1;
         size = fIndex[i].chunk_length;
         

Modified: 
haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h
===================================================================
--- haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h 
2009-11-29 20:51:12 UTC (rev 34353)
+++ haiku/trunk/src/add-ons/media/plugins/avi_reader/libOpenDML/StandardIndex.h 
2009-11-29 21:07:35 UTC (rev 34354)
@@ -26,7 +26,6 @@
 #define _STANDARD_INDEX_H
 
 #include "Index.h"
-#include "avi.h"
 
 class StandardIndex : public Index
 {


Other related posts: