Browse code

Implement av_find_best_stream.

Originally committed as revision 26104 to svn://svn.ffmpeg.org/ffmpeg/trunk

Nicolas George authored on 2010/12/27 18:08:20
Showing 3 changed files
... ...
@@ -13,6 +13,9 @@ libavutil:   2009-03-08
13 13
 
14 14
 API changes, most recent first:
15 15
 
16
+2010-12-XX - r26104 - lavformat 52.91.0 - av_find_best_stream()
17
+  Add av_find_best_stream to libavformat/avformat.h.
18
+
16 19
 2010-12-27 - r26103 - lavf 52.90.0
17 20
   Add AVFMT_NOSTREAMS flag for formats with no streams,
18 21
   like e.g. text metadata.
... ...
@@ -22,7 +22,7 @@
22 22
 #define AVFORMAT_AVFORMAT_H
23 23
 
24 24
 #define LIBAVFORMAT_VERSION_MAJOR 52
25
-#define LIBAVFORMAT_VERSION_MINOR 90
25
+#define LIBAVFORMAT_VERSION_MINOR 91
26 26
 #define LIBAVFORMAT_VERSION_MICRO  0
27 27
 
28 28
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
... ...
@@ -1141,6 +1141,37 @@ AVFormatContext *avformat_alloc_context(void);
1141 1141
 int av_find_stream_info(AVFormatContext *ic);
1142 1142
 
1143 1143
 /**
1144
+ * Find the "best" stream in the file.
1145
+ * The best stream is determined according to various heuristics as the most
1146
+ * likely to be what the user expects.
1147
+ * If the decoder parameter is non-NULL, av_find_best_stream will find the
1148
+ * default decoder for the stream's codec; streams for which no decoder can
1149
+ * be found are ignored.
1150
+ *
1151
+ * @param ic                media file handle
1152
+ * @param type              stream type: video, audio, subtitles, etc.
1153
+ * @param wanted_stream_nb  user-requested stream number,
1154
+ *                          or -1 for automatic selection
1155
+ * @param related_stream    try to find a stream related (eg. in the same
1156
+ *                          program) to this one, or -1 if none
1157
+ * @param decoder_ret       if non-NULL, returns the decoder for the
1158
+ *                          selected stream
1159
+ * @param flags             flags; none are currently defined
1160
+ * @return  the non-negative stream number in case of success,
1161
+ *          AVERROR_STREAM_NOT_FOUND if no stream with the requested type
1162
+ *          could be found,
1163
+ *          AVERROR_DECODER_NOT_FOUND if streams were found but no decoder
1164
+ * @note  If av_find_best_stream returns successfully and decoder_ret is not
1165
+ *        NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec.
1166
+ */
1167
+int av_find_best_stream(AVFormatContext *ic,
1168
+                        enum AVMediaType type,
1169
+                        int wanted_stream_nb,
1170
+                        int related_stream,
1171
+                        AVCodec **decoder_ret,
1172
+                        int flags);
1173
+
1174
+/**
1144 1175
  * Read a transport packet from a media file.
1145 1176
  *
1146 1177
  * This function is obsolete and should never be used.
... ...
@@ -2458,6 +2458,67 @@ int av_find_stream_info(AVFormatContext *ic)
2458 2458
     return ret;
2459 2459
 }
2460 2460
 
2461
+static AVProgram *find_program_from_stream(AVFormatContext *ic, int s)
2462
+{
2463
+    int i, j;
2464
+
2465
+    for (i = 0; i < ic->nb_programs; i++)
2466
+        for (j = 0; j < ic->programs[i]->nb_stream_indexes; j++)
2467
+            if (ic->programs[i]->stream_index[j] == s)
2468
+                return ic->programs[i];
2469
+    return NULL;
2470
+}
2471
+
2472
+int av_find_best_stream(AVFormatContext *ic,
2473
+                        enum AVMediaType type,
2474
+                        int wanted_stream_nb,
2475
+                        int related_stream,
2476
+                        AVCodec **decoder_ret,
2477
+                        int flags)
2478
+{
2479
+    int i, nb_streams = ic->nb_streams, stream_number = 0;
2480
+    int ret = AVERROR_STREAM_NOT_FOUND, best_count = -1;
2481
+    unsigned *program = NULL;
2482
+    AVCodec *decoder = NULL, *best_decoder = NULL;
2483
+
2484
+    if (related_stream >= 0 && wanted_stream_nb < 0) {
2485
+        AVProgram *p = find_program_from_stream(ic, related_stream);
2486
+        if (p) {
2487
+            program = p->stream_index;
2488
+            nb_streams = p->nb_stream_indexes;
2489
+        }
2490
+    }
2491
+    for (i = 0; i < nb_streams; i++) {
2492
+        AVStream *st = ic->streams[program ? program[i] : i];
2493
+        AVCodecContext *avctx = st->codec;
2494
+        if (avctx->codec_type != type)
2495
+            continue;
2496
+        if (wanted_stream_nb >= 0 && stream_number++ != wanted_stream_nb)
2497
+            continue;
2498
+        if (decoder_ret) {
2499
+            decoder = avcodec_find_decoder(ic->streams[i]->codec->codec_id);
2500
+            if (!decoder) {
2501
+                if (ret < 0)
2502
+                    ret = AVERROR_DECODER_NOT_FOUND;
2503
+                continue;
2504
+            }
2505
+        }
2506
+        if (best_count >= st->codec_info_nb_frames)
2507
+            continue;
2508
+        best_count = st->codec_info_nb_frames;
2509
+        ret = i;
2510
+        best_decoder = decoder;
2511
+        if (program && i == nb_streams - 1 && ret < 0) {
2512
+            program = NULL;
2513
+            nb_streams = ic->nb_streams;
2514
+            i = 0; /* no related stream found, try again with everything */
2515
+        }
2516
+    }
2517
+    if (decoder_ret)
2518
+        *decoder_ret = best_decoder;
2519
+    return ret;
2520
+}
2521
+
2461 2522
 /*******************************************************/
2462 2523
 
2463 2524
 int av_read_play(AVFormatContext *s)