]> git.sesse.net Git - ffmpeg/blobdiff - libavformat/asfdec.c
In dv decoder, set sample aspect aspect ratio, fix issue #1612
[ffmpeg] / libavformat / asfdec.c
index ab96cc433993038354de3c4b89b974d0d8500ae3..6741f8ce17b987e4a45e583b2aae5ac442dc64a6 100644 (file)
@@ -35,6 +35,7 @@ void ff_mms_set_stream_selection(URLContext *h, AVFormatContext *format);
 #undef NDEBUG
 #include <assert.h>
 
+#define ASF_MAX_STREAMS 127
 #define FRAME_HEADER_SIZE 17
 // Fix Me! FRAME_HEADER_SIZE may be different.
 
@@ -204,9 +205,10 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
     get_byte(pb);
     memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid));
     for(;;) {
+        uint64_t gpos= url_ftell(pb);
         get_guid(pb, &g);
         gsize = get_le64(pb);
-        dprintf(s, "%08"PRIx64": ", url_ftell(pb) - 24);
+        dprintf(s, "%08"PRIx64": ", gpos);
         print_guid(&g);
         dprintf(s, "  size=0x%"PRIx64"\n", gsize);
         if (!guidcmp(&g, &ff_asf_data_header)) {
@@ -243,6 +245,11 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
             int64_t pos1, pos2, start_time;
             int test_for_ext_stream_audio, is_dvr_ms_audio=0;
 
+            if (s->nb_streams == ASF_MAX_STREAMS) {
+                av_log(s, AV_LOG_ERROR, "too many streams\n");
+                return AVERROR(EINVAL);
+            }
+
             pos1 = url_ftell(pb);
 
             st = av_new_stream(s, 0);
@@ -268,6 +275,9 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
                 type = AVMEDIA_TYPE_AUDIO;
             } else if (!guidcmp(&g, &ff_asf_video_stream)) {
                 type = AVMEDIA_TYPE_VIDEO;
+            } else if (!guidcmp(&g, &ff_asf_jfif_media)) {
+                type = AVMEDIA_TYPE_VIDEO;
+                st->codec->codec_id = CODEC_ID_MJPEG;
             } else if (!guidcmp(&g, &ff_asf_command_stream)) {
                 type = AVMEDIA_TYPE_DATA;
             } else if (!guidcmp(&g, &ff_asf_ext_stream_embed_stream_header)) {
@@ -351,7 +361,8 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
                     st->codec->frame_size = 1;
                     break;
                 }
-            } else if (type == AVMEDIA_TYPE_VIDEO) {
+            } else if (type == AVMEDIA_TYPE_VIDEO &&
+                       gsize - (url_ftell(pb) - pos1 + 24) >= 51) {
                 get_le32(pb);
                 get_le32(pb);
                 get_byte(pb);
@@ -379,7 +390,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
                     st->codec->palctrl = av_mallocz(sizeof(AVPaletteControl));
 #if HAVE_BIGENDIAN
                     for (i = 0; i < FFMIN(st->codec->extradata_size, AVPALETTE_SIZE)/4; i++)
-                        st->codec->palctrl->palette[i] = bswap_32(((uint32_t*)st->codec->extradata)[i]);
+                        st->codec->palctrl->palette[i] = av_bswap32(((uint32_t*)st->codec->extradata)[i]);
 #else
                     memcpy(st->codec->palctrl->palette, st->codec->extradata,
                            FFMIN(st->codec->extradata_size, AVPALETTE_SIZE));
@@ -389,8 +400,16 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 
                 st->codec->codec_tag = tag1;
                 st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1);
-                if(tag1 == MKTAG('D', 'V', 'R', ' '))
+                if(tag1 == MKTAG('D', 'V', 'R', ' ')){
                     st->need_parsing = AVSTREAM_PARSE_FULL;
+                    // issue658 containse wrong w/h and MS even puts a fake seq header with wrong w/h in extradata while a correct one is in te stream. maximum lameness
+                    st->codec->width  =
+                    st->codec->height = 0;
+                    av_freep(&st->codec->extradata);
+                    st->codec->extradata_size=0;
+                }
+                if(st->codec->codec_id == CODEC_ID_H264)
+                    st->need_parsing = AVSTREAM_PARSE_FULL_ONCE;
             }
             pos2 = url_ftell(pb);
             url_fskip(pb, gsize - (pos2 - pos1 + 24));
@@ -448,7 +467,16 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
                     value_len  = get_le16(pb);
                     if (!value_type && value_len%2)
                         value_len += 1;
-                    get_tag(s, name, value_type, value_len);
+                    /**
+                     * My sample has that stream set to 0 maybe that mean the container.
+                     * Asf stream count start at 1. I am using 0 to the container value since it's unused
+                     */
+                    if (!strcmp(name, "AspectRatioX")){
+                        dar[0].num= get_value(s->pb, value_type);
+                    } else if(!strcmp(name, "AspectRatioY")){
+                        dar[0].den= get_value(s->pb, value_type);
+                    } else
+                        get_tag(s, name, value_type, value_len);
             }
         } else if (!guidcmp(&g, &ff_asf_metadata_header)) {
             int n, stream_num, name_len, value_len, value_type, value_num;
@@ -516,11 +544,13 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
 
             // there could be a optional stream properties object to follow
             // if so the next iteration will pick it up
+            continue;
         } else if (!guidcmp(&g, &ff_asf_head1_guid)) {
             int v1, v2;
             get_guid(pb, &g);
             v1 = get_le32(pb);
             v2 = get_le16(pb);
+            continue;
         } else if (!guidcmp(&g, &ff_asf_marker_header)) {
             int i, count, name_len;
             char name[1024];
@@ -584,8 +614,10 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
                     av_log(s, AV_LOG_WARNING, "Digital signature detected, decoding will likely fail!\n");
                 }
             }
-            url_fseek(pb, gsize - 24, SEEK_CUR);
         }
+        if(url_ftell(pb) != gpos + gsize)
+            av_log(s, AV_LOG_DEBUG, "gpos mismatch our pos=%"PRIu64", end=%"PRIu64"\n", url_ftell(pb)-gpos, gsize);
+        url_fseek(pb, gpos + gsize, SEEK_SET);
     }
     get_guid(pb, &g);
     get_le64(pb);
@@ -603,11 +635,16 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
             AVStream *st = s->streams[stream_num];
             if (!st->codec->bit_rate)
                 st->codec->bit_rate = bitrate[i];
-            if (dar[i].num > 0 && dar[i].den > 0)
+            if (dar[i].num > 0 && dar[i].den > 0){
                 av_reduce(&st->sample_aspect_ratio.num,
                           &st->sample_aspect_ratio.den,
                           dar[i].num, dar[i].den, INT_MAX);
-//av_log(s, AV_LOG_ERROR, "dar %d:%d sar=%d:%d\n", dar[i].num, dar[i].den, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
+            } else if ((dar[0].num > 0) && (dar[0].den > 0) && (st->codec->codec_type==AVMEDIA_TYPE_VIDEO)) // Use ASF container value if the stream doesn't AR set.
+                av_reduce(&st->sample_aspect_ratio.num,
+                          &st->sample_aspect_ratio.den,
+                          dar[0].num, dar[0].den, INT_MAX);
+
+//av_log(s, AV_LOG_INFO, "i=%d, st->codec->codec_type:%d, dar %d:%d sar=%d:%d\n", i, st->codec->codec_type, dar[i].num, dar[i].den, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
 
             // copy and convert language codes to the frontend
             if (asf->streams[i].stream_language_index < 128) {
@@ -616,7 +653,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
                     const char primary_tag[3] = { rfc1766[0], rfc1766[1], '\0' }; // ignore country code if any
                     const char *iso6392 = av_convert_lang_to(primary_tag, AV_LANG_ISO639_2_BIBL);
                     if (iso6392)
-                        av_metadata_set(&st->metadata, "language", iso6392);
+                        av_metadata_set2(&st->metadata, "language", iso6392, 0);
                 }
             }
         }
@@ -888,12 +925,12 @@ static int ff_asf_parse_packet(AVFormatContext *s, ByteIOContext *pb, AVPacket *
             asf_st->pkt.pos =
             asf_st->packet_pos= asf->packet_pos;
 //printf("new packet: stream:%d key:%d packet_key:%d audio:%d size:%d\n",
-//asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & PKT_FLAG_KEY,
+//asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & AV_PKT_FLAG_KEY,
 //s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO, asf->packet_obj_size);
             if (s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
                 asf->packet_key_frame = 1;
             if (asf->packet_key_frame)
-                asf_st->pkt.flags |= PKT_FLAG_KEY;
+                asf_st->pkt.flags |= AV_PKT_FLAG_KEY;
         }
 
         /* read data */
@@ -1046,7 +1083,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos,
     int64_t pts;
     int64_t pos= *ppos;
     int i;
-    int64_t start_pos[s->nb_streams];
+    int64_t start_pos[ASF_MAX_STREAMS];
 
     for(i=0; i<s->nb_streams; i++){
         start_pos[i]= pos;
@@ -1068,7 +1105,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos,
         pts= pkt->pts;
 
         av_free_packet(pkt);
-        if(pkt->flags&PKT_FLAG_KEY){
+        if(pkt->flags&AV_PKT_FLAG_KEY){
             i= pkt->stream_index;
 
             asf_st= s->streams[i]->priv_data;