gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r10004: Add support for FLVs with em


From: Bastiaan Jacques
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10004: Add support for FLVs with embedded H.264 video:
Date: Sun, 19 Oct 2008 21:05:30 +0200
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10004
committer: Bastiaan Jacques <address@hidden>
branch nick: trunk
timestamp: Sun 2008-10-19 21:05:30 +0200
message:
  Add support for FLVs with embedded H.264 video:
  libmedia/FLVParser.cpp: For h264, skip four extra bytes per FLV spec.
    Stop attempting to parse width and height for h.263, since it's not
    necessary (and our values for other video codecs were bogus).
  libmedia/FLVParser.h: Add FLV-specific extradata (for h264).
  libmedia/MediaParser.h: Add h264 to codec type enum.
  libmedia/ffmpeg/VideoDecoderFfmpeg.cpp: Add FLVParser's extradata.
  libmedia/gst: Update interfaces to include FLVParser's extradata.
modified:
  libmedia/FLVParser.cpp
  libmedia/FLVParser.h
  libmedia/MediaParser.h
  libmedia/ffmpeg/VideoDecoderFfmpeg.cpp
  libmedia/gst/MediaHandlerGst.cpp
  libmedia/gst/VideoDecoderGst.cpp
  libmedia/gst/VideoDecoderGst.h
=== modified file 'libmedia/FLVParser.cpp'
--- a/libmedia/FLVParser.cpp    2008-09-30 22:44:56 +0000
+++ b/libmedia/FLVParser.cpp    2008-10-19 19:05:30 +0000
@@ -370,11 +370,26 @@
 
                boost::uint16_t codec = (tag[11] & 0x0f) >> 0;
 
-        if (codec == VIDEO_CODEC_VP6 || codec == VIDEO_CODEC_VP6A)
-        {
-            _stream->read_byte();
-            --bodyLength;
-        }
+               if (codec == VIDEO_CODEC_VP6 || codec == VIDEO_CODEC_VP6A)
+               {
+                       _stream->read_byte();
+                       --bodyLength;
+               }
+
+               bool header = false;
+
+               if (codec == VIDEO_CODEC_H264) {
+                       boost::uint8_t packettype = _stream->read_byte();
+                       IF_VERBOSE_PARSE( log_debug(_("AVC packet type: %d"), 
(unsigned)packettype) );
+
+                       header = (packettype == 0);
+
+                       // 24-bits value for composition time offset ignored 
for now.
+                       boost::uint8_t tmp[3];
+                       _stream->read(tmp, 3);
+
+                       bodyLength -= 4;
+               }
                
                if ( doIndex )
                {
@@ -399,74 +414,18 @@
                // video format has been noted, so we do that now
                if ( ! _videoInfo.get() )
                {
-                       // Set standard guessed size...
-                       boost::uint16_t width = 320;
-                       boost::uint16_t height = 240;
-
-                       // Extract the video size from the videodata header
-                       if (codec == VIDEO_CODEC_H263) {
-
-                               // We're going to re-read some data here
-                               // (can likely avoid with a better cleanup)
-
-                               size_t bkpos = _stream->tell();
-                               if ( _stream->seek(dataPosition) ) {
-                                       log_error(" Couldn't seek to VideoTag 
data position -- should never happen, as we just read that!");
-                                       _parsingComplete=true;
-                                       _indexingCompleted=true;
-                                       return false;
-                               }
-                               boost::uint8_t videohead[12];
-
-                               int actuallyRead = _stream->read(videohead, 12);
-                               _stream->seek(bkpos); // rewind
-
-                               if ( actuallyRead < 12 )
-                               {
-               log_error("FLVParser::parseNextTag: can't read H263 video 
header (needed 12 bytes, only got %d)", actuallyRead);
-               _parsingComplete=true;
-               _indexingCompleted=true;
-               return false;
-                               }
-
-                               bool sizebit1 = (videohead[3] & 0x02);
-                               bool sizebit2 = (videohead[3] & 0x01);
-                               bool sizebit3 = (videohead[4] & 0x80);
-
-                               // First some predefined sizes
-                               if (!sizebit1 && sizebit2 && !sizebit3 ) {
-                                       width = 352;
-                                       height = 288;
-                               } else if (!sizebit1 && sizebit2 && sizebit3 ) {
-                                       width = 176;
-                                       height = 144;
-                               } else if (sizebit1 && !sizebit2 && !sizebit3 ) 
{
-                                       width = 128;
-                                       height = 96;
-                               } else if (sizebit1 && !sizebit2 && sizebit3 ) {
-                                       width = 320;
-                                       height = 240;
-                               } else if (sizebit1 && sizebit2 && !sizebit3 ) {
-                                       width = 160;
-                                       height = 120;
-
-                               // Then the custom sizes (1 byte - untested and 
ugly)
-                               } else if (!sizebit1 && !sizebit2 && !sizebit3 
) {
-                                       width = (videohead[4] & 0x40) | 
(videohead[4] & 0x20) | (videohead[4] & 0x20) | (videohead[4] & 0x08) | 
(videohead[4] & 0x04) | (videohead[4] & 0x02) | (videohead[4] & 0x01) | 
(videohead[5] & 0x80);
-
-                                       height = (videohead[5] & 0x40) | 
(videohead[5] & 0x20) | (videohead[5] & 0x20) | (videohead[5] & 0x08) | 
(videohead[5] & 0x04) | (videohead[5] & 0x02) | (videohead[5] & 0x01) | 
(videohead[6] & 0x80);
-
-                               // Then the custom sizes (2 byte - untested and 
ugly)
-                               } else if (!sizebit1 && !sizebit2 && sizebit3 ) 
{
-                                       width = (videohead[4] & 0x40) | 
(videohead[4] & 0x20) | (videohead[4] & 0x20) | (videohead[4] & 0x08) | 
(videohead[4] & 0x04) | (videohead[4] & 0x02) | (videohead[4] & 0x01) | 
(videohead[5] & 0x80) | (videohead[5] & 0x40) | (videohead[5] & 0x20) | 
(videohead[5] & 0x20) | (videohead[5] & 0x08) | (videohead[5] & 0x04) | 
(videohead[5] & 0x02) | (videohead[5] & 0x01) | (videohead[6] & 0x80);
-
-                                       height = (videohead[6] & 0x40) | 
(videohead[6] & 0x20) | (videohead[6] & 0x20) | (videohead[6] & 0x08) | 
(videohead[6] & 0x04) | (videohead[6] & 0x02) | (videohead[6] & 0x01) | 
(videohead[7] & 0x80) | (videohead[7] & 0x40) | (videohead[7] & 0x20) | 
(videohead[7] & 0x20) | (videohead[7] & 0x08) | (videohead[7] & 0x04) | 
(videohead[7] & 0x02) | (videohead[7] & 0x01) | (videohead[8] & 0x80);
-                               }
-
+                       _videoInfo.reset( new VideoInfo(codec, 0 /* width */, 0 
/* height */, 0 /*frameRate*/, 0 /*duration*/, FLASH /*codec type*/) );
+
+                       if (header) {
+                               boost::uint8_t* newbuf = new 
boost::uint8_t[frame->dataSize()];
+                               memcpy(newbuf, frame->data(), 
frame->dataSize());
+
+                               _videoInfo->extra.reset( 
+                                       new ExtraVideoInfoFlv(newbuf, 
frame->dataSize())
+                               );
                        }
 
                        // Create the videoinfo
-                       _videoInfo.reset( new VideoInfo(codec, width, height, 0 
/*frameRate*/, 0 /*duration*/, FLASH /*codec type*/) );
                }
 
                // Release the stream lock 
@@ -627,6 +586,7 @@
        // We won't need frameNum, so will set to zero...
        // TODO: fix this ?
        // NOTE: ownership of 'data' is transferred here
+
        frame.reset( new EncodedVideoFrame(data, dataSize, 0, timestamp) );
        return frame;
 }

=== modified file 'libmedia/FLVParser.h'
--- a/libmedia/FLVParser.h      2008-09-02 23:15:48 +0000
+++ b/libmedia/FLVParser.h      2008-10-19 19:05:30 +0000
@@ -42,6 +42,21 @@
 namespace gnash {
 namespace media {
 
+
+
+class ExtraVideoInfoFlv : public VideoInfo::ExtraInfo
+{
+public:
+        ExtraVideoInfoFlv(boost::uint8_t* extradata, size_t datasize)
+                :
+                data(extradata),
+                size(datasize)
+        {
+        }
+        boost::scoped_array<boost::uint8_t> data;
+        size_t size;
+};
+
 /// The FLVParser class parses FLV streams
 class DSOEXPORT FLVParser : public MediaParser
 {

=== modified file 'libmedia/MediaParser.h'
--- a/libmedia/MediaParser.h    2008-10-05 00:08:38 +0000
+++ b/libmedia/MediaParser.h    2008-10-19 19:05:30 +0000
@@ -89,7 +89,9 @@
        VIDEO_CODEC_VP6A = 5,
 
        /// Screenvideo2 codec
-       VIDEO_CODEC_SCREENVIDEO2 = 6
+       VIDEO_CODEC_SCREENVIDEO2 = 6,
+
+       VIDEO_CODEC_H264 = 7
 };
 
 std::ostream& operator<< (std::ostream& os, const videoCodecType& t);

=== modified file 'libmedia/ffmpeg/VideoDecoderFfmpeg.cpp'
--- a/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp    2008-10-01 15:15:40 +0000
+++ b/libmedia/ffmpeg/VideoDecoderFfmpeg.cpp    2008-10-19 19:05:30 +0000
@@ -40,6 +40,8 @@
 #include <boost/format.hpp>
 #include <algorithm>
 
+#include "FLVParser.h"
+
 namespace gnash {
 namespace media {
 
@@ -129,10 +131,15 @@
     int extradataSize=0;
     if ( info.extra.get() )
     {
-        assert(dynamic_cast<ExtraVideoInfoFfmpeg*>(info.extra.get()));
-        const ExtraVideoInfoFfmpeg& ei = 
static_cast<ExtraVideoInfoFfmpeg&>(*info.extra);
-        extradata = ei.data;
-        extradataSize = ei.dataSize;
+        if (dynamic_cast<ExtraVideoInfoFfmpeg*>(info.extra.get())) {
+            const ExtraVideoInfoFfmpeg& ei = 
static_cast<ExtraVideoInfoFfmpeg&>(*info.extra);
+            extradata = ei.data;
+            extradataSize = ei.dataSize;
+        } else if (dynamic_cast<ExtraVideoInfoFlv*>(info.extra.get())) {
+            const ExtraVideoInfoFlv& ei = 
static_cast<ExtraVideoInfoFlv&>(*info.extra);
+            extradata = ei.data.get();
+            extradataSize = ei.size;
+        } else assert(0);
     }
     init(codec_id, info.width, info.height, extradata, extradataSize);
 }
@@ -170,14 +177,9 @@
         throw MediaException(msg.str());
     }
     
-    ctx->width = width;
-    ctx->height = height;
-
     log_debug(_("VideoDecoder: initialized FFMPEG codec %s (%d)"), 
                _videoCodec->name, (int)codecId);
 
-    assert(ctx->width > 0);
-    assert(ctx->height > 0);
 }
 
 VideoDecoderFfmpeg::~VideoDecoderFfmpeg()
@@ -279,7 +281,6 @@
 std::auto_ptr<image::ImageBase>
 VideoDecoderFfmpeg::decode(const boost::uint8_t* input, boost::uint32_t 
input_size)
 {
-
     // This object shouldn't exist if there's no codec, as it can'
     // do anything anyway.
     assert(_videoCodecCtx.get());
@@ -343,6 +344,8 @@
 {
         // Find the decoder and init the parser
         switch(format) {
+                case VIDEO_CODEC_H264:
+                         return CODEC_ID_H264;
                 case VIDEO_CODEC_H263:
                         // CODEC_ID_H263I didn't work with Lavc51.50.0
                         // and NetStream-SquareTest.swf

=== modified file 'libmedia/gst/MediaHandlerGst.cpp'
--- a/libmedia/gst/MediaHandlerGst.cpp  2008-10-05 00:08:38 +0000
+++ b/libmedia/gst/MediaHandlerGst.cpp  2008-10-19 19:05:30 +0000
@@ -75,7 +75,16 @@
        int width = info.width;
        int height = info.height;
 
-       std::auto_ptr<VideoDecoder> ret( new VideoDecoderGst(format, width, 
height) );
+       boost::uint8_t* extradata = 0;
+       size_t datasize = 0;
+
+       ExtraVideoInfoFlv* extrainfo = 
dynamic_cast<ExtraVideoInfoFlv*>(info.extra.get());
+       if (extrainfo) {
+               extradata = extrainfo->data.get();
+                datasize = extrainfo->size;
+       }
+
+       std::auto_ptr<VideoDecoder> ret( new VideoDecoderGst(format, width, 
height, extradata, datasize) );
        return ret;
 }
 

=== modified file 'libmedia/gst/VideoDecoderGst.cpp'
--- a/libmedia/gst/VideoDecoderGst.cpp  2008-10-07 19:32:41 +0000
+++ b/libmedia/gst/VideoDecoderGst.cpp  2008-10-19 19:05:30 +0000
@@ -39,13 +39,27 @@
 }
 
 
-VideoDecoderGst::VideoDecoderGst(videoCodecType codec_type, int width, int 
height)
+VideoDecoderGst::VideoDecoderGst(videoCodecType codec_type, int width, int 
height,
+                                 const boost::uint8_t* extradata, size_t 
extradatasize)
 {
     // init GStreamer. TODO: what about doing this in MediaHandlerGst ctor?
     gst_init (NULL, NULL);
 
   GstCaps* caps;  
   switch (codec_type) {
+    case VIDEO_CODEC_H264:
+    {
+      caps = gst_caps_new_simple ("video/x-h264",
+                                      NULL);
+
+      if (extradata && extradatasize) {
+
+          GstBuffer* buf = gst_buffer_new_and_alloc(extradatasize);
+          memcpy(GST_BUFFER_DATA(buf), extradata, extradatasize);
+          gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL);
+      }
+      break;
+    } 
     case VIDEO_CODEC_H263:
       caps = gst_caps_new_simple ("video/x-flash-video",
                                       NULL);

=== modified file 'libmedia/gst/VideoDecoderGst.h'
--- a/libmedia/gst/VideoDecoderGst.h    2008-10-13 09:43:19 +0000
+++ b/libmedia/gst/VideoDecoderGst.h    2008-10-19 19:05:30 +0000
@@ -76,7 +76,8 @@
 class DSOEXPORT VideoDecoderGst : public VideoDecoder
 {
 public:
-    VideoDecoderGst(videoCodecType codec_type, int width, int height);
+    VideoDecoderGst(videoCodecType codec_type, int width, int height,
+                    const boost::uint8_t* extradata, size_t extradatasize);
     VideoDecoderGst(GstCaps* caps);
     ~VideoDecoderGst();
 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]