vtl: update ffprobe csv parsing
authorRobin Gareus <robin@gareus.org>
Fri, 29 Mar 2013 10:07:20 +0000 (11:07 +0100)
committerRobin Gareus <robin@gareus.org>
Fri, 29 Mar 2013 11:36:08 +0000 (12:36 +0100)
gtk2_ardour/transcode_ffmpeg.cc

index 57121e257da937cd9c51021995727b29a99f73b9..e886c64f6441c01e8636b1083a584c3603654970 100644 (file)
@@ -98,8 +98,8 @@ TranscodeFfmpeg::probe ()
        char **argp;
        argp=(char**) calloc(7,sizeof(char*));
        argp[0] = strdup(ffprobe_exe.c_str());
-       argp[1] = strdup("-print_format"); // "-of"  ; new version and avprobe compat but avprobe does not yet support csv
-       argp[2] = strdup("csv"); // TODO use "csv=nk=0" and parse key/value pairs -> ffprobe version agnostic or parse XML or JSON key/value
+       argp[1] = strdup("-print_format");
+       argp[2] = strdup("csv=nk=0");
        argp[3] = strdup("-show_format");
        argp[4] = strdup("-show_streams");
        argp[5] = strdup(infile.c_str());
@@ -123,113 +123,100 @@ TranscodeFfmpeg::probe ()
        m_codec.clear();
        m_audio.clear();
 
+#define PARSE_FRACTIONAL_FPS \
+       { \
+               std::string::size_type pos; \
+               m_fps = atof(value.c_str()); \
+               pos = value.find_first_of('/'); \
+               if (pos != std::string::npos) { \
+                       m_fps = atof(value.substr(0, pos).c_str()) / atof(value.substr(pos+1).c_str()); \
+               } \
+       }
+
        for (std::vector<std::vector<std::string> >::iterator i = lines.begin(); i != lines.end(); ++i) {
                if (i->at(0) == X_("format")) {
                        /* format,filename,#streams,format-name,format-long-name,start-time,duration,size,bitrate */
                } else
                if (i->at(0) == X_("stream")) {
-                       /*--------- Stream format
-                        * stream,index,codec-name,codec-name-long,PROFILE,
-                        *   codec_time_base,codec_tag_string,codec_tag[hex],
-                        * VIDEO:
-                        *   width,height,has_b_frames,sample_aspect_ratio,display_aspect_ratio
-                        *   pix_fmt,level,
-                        *   timecode
-                        * AUDIO:
-                        *   sample_fmt,sample_rate,channels,bits_per_sample
-                        *
-                        * all cont'd;
-                        *   r_frame_rate,avg_frame_rate,time_base,start_time,duration,
-                        *   bit_rate,nb_frames,nb_read_frames,nb_read_packets
-                        *
-                        *---------- Example
-                        * stream,0,mpeg2video,MPEG-2 video,video,1/50,[0][0][0][0],0x0000,720,576,1,16:15,4:3,yuv420p,8,00:02:30:00,0x1e0,25/1,25/1,1/90000,0.360000,N/A,7000000,N/A,N/A,N/A
-                        * stream,1,ac3,ATSC A/52A (AC-3),audio,1/48000,[0][0][0][0],0x0000,s16,48000,6,0,-1,-1.000000,-1.000000,-1.000000,-1.000000,0x80,0/0,0/0,1/90000,0.280000,312.992000,448000,N/A,N/A,N/A
-                        * stream,2,ac3,ATSC A/52A (AC-3),audio,1/48000,[0][0][0][0],0x0000,s16,48000,2,0,-1,-1.000000,-1.000000,-1.000000,-1.000000,0x82,0/0,0/0,1/90000,0.280000,312.992000,384000,N/A,N/A,N/A
-                        * stream,3,ac3,ATSC A/52A (AC-3),audio,1/48000,[0][0][0][0],0x0000,s16,48000,2,0,-1,-1.000000,-1.000000,-1.000000,-1.000000,0x81,0/0,0/0,1/90000,0.280000,312.992000,192000,N/A,N/A,N/A
-                        */
-                       if (i->at(4) == X_("video") && m_width == 0) {
-                               std::string::size_type pos;
-
-                               m_width = atoi(i->at(8).c_str());
-                               m_height = atoi(i->at(9).c_str());
-                               m_codec = i->at(3) + " -- " + i->at(2);
-                               m_fps = atof(i->at(17).c_str());
-
-                               pos = i->at(17).find_first_of('/');
-                               if (pos != std::string::npos) {
-                                       m_fps = atof(i->at(17).substr(0, pos).c_str()) / atof(i->at(17).substr(pos+1).c_str());
+                       if (i->at(5) == X_("codec_type=video") && m_width == 0) {
+
+                               for (std::vector<std::string>::iterator kv = i->begin(); kv != i->end(); ++kv) {
+                                       const size_t kvsep = kv->find('=');
+                                       if(kvsep == std::string::npos) continue;
+                                       std::string key = kv->substr(0, kvsep);
+                                       std::string value = kv->substr(kvsep + 1);
+
+                                       if (key == X_("width")) {
+                                               m_width = atoi(value.c_str());
+                                       } else if (key == X_("height")) {
+                                               m_height = atoi(value.c_str());
+                                       } else if (key == X_("codec_name")) {
+                                               if (!m_codec.empty()) m_codec += " ";
+                                               m_codec += value;
+                                       } else if (key == X_("codec_long_name")) {
+                                               if (!m_codec.empty()) m_codec += " ";
+                                               m_codec += "[" + value + "]";
+                                       } else if (key == X_("codec_tag_string")) {
+                                               if (!m_codec.empty()) m_codec += " ";
+                                               m_codec += "(" + value + ")";
+                                       } else if (key == X_("r_frame_rate")) {
+                                               PARSE_FRACTIONAL_FPS
+                                       } else if (key == X_("time_base") && m_fps == 0) {
+                                               PARSE_FRACTIONAL_FPS
+                                       } else if (key == X_("timecode") && m_duration == 0) {
+                                               int h,m,s; char f[7];
+                                               if (sscanf(i->at(16).c_str(), "%d:%d:%d:%s",&h,&m,&s,f) == 4) {
+                                                       m_duration = (ARDOUR::framecnt_t) floor(m_fps * (
+                                                                       h * 3600.0
+                                                               + m * 60.0
+                                                               + s * 1.0
+                                                               + atoi(f) / pow(10, strlen(f))
+                                                       ));
+                                               }
+                                       } else if (key == X_("duration_ts")) {
+                                               m_duration = atof(value.c_str());
+                                       } else if (key == X_("duration") && m_duration == 0 && m_fps != 0) {
+                                               m_duration = atof(value.c_str()) * m_fps;
+                                       } else if (key == X_("display_aspect_ratio")) {
+                                               std::string::size_type pos;
+                                               pos = value.find_first_of(':');
+                                               if (pos != std::string::npos && atof(value.substr(pos+1).c_str()) != 0) {
+                                                       m_aspect = atof(value.substr(0, pos).c_str()) / atof(value.substr(pos+1).c_str());
+                                               }
+                                       }
                                }
 
-                               pos = i->at(12).find_first_of(':');
-                               m_aspect = 0;
-                               if (pos != std::string::npos && atof(i->at(12).substr(pos+1).c_str()) != 0) {
-                                       m_aspect = atof(i->at(12).substr(0, pos).c_str()) / atof(i->at(12).substr(pos+1).c_str());
-                               }
                                if (m_aspect == 0) {
                                        m_aspect = (double)m_width / (double)m_height;
                                }
 
-                               int h,m,s; char f[7];
-                               if (sscanf(i->at(15).c_str(), "%d:%d:%d:%s",&h,&m,&s,f) == 4) {
-                                       m_duration = (ARDOUR::framecnt_t) floor(m_fps * (
-                                                       h * 3600.0
-                                               + m * 60.0
-                                               + s * 1.0
-                                               + atoi(f) / pow(10, strlen(f))
-                                       ));
-                               } else {
-                                       m_duration = atof(i->at(21).c_str()) * m_fps;
-                               }
-
-                       } else if (i->at(4) == X_("audio")) {
+                       } else if (i->at(5) == X_("codec_type=audio")) { /* new ffprobe */
                                AudioStream as;
-                               as.name = i->at(3) + " " + i->at(2) + " " + i->at(8) + " " + i->at(9);
-                               as.stream_id  = i->at(1);
-                               as.channels   = atoi(i->at(10).c_str());
-                               m_audio.push_back(as);
-
-                       } else if (i->at(5) == X_("video") && m_width == 0) { /* new ffprobe */
-                               std::string::size_type pos;
-
-                               m_width = atoi(i->at(9).c_str());
-                               m_height = atoi(i->at(10).c_str());
-                               m_codec = i->at(3) + " -- " + i->at(2);
-                               m_fps = atof(i->at(18).c_str());
-
-                               pos = i->at(18).find_first_of('/');
-                               if (pos != std::string::npos) {
-                                       m_fps = atof(i->at(18).substr(0, pos).c_str()) / atof(i->at(18).substr(pos+1).c_str());
-                               }
+                               for (std::vector<std::string>::iterator kv = i->begin(); kv != i->end(); ++kv) {
+                                       const size_t kvsep = kv->find('=');
+                                       if(kvsep == std::string::npos) continue;
+                                       std::string key = kv->substr(0, kvsep);
+                                       std::string value = kv->substr(kvsep + 1);
+
+                                       if (key == X_("channels")) {
+                                               as.channels   = atoi(value.c_str());
+                                       } else if (key == X_("index")) {
+                                               as.stream_id  = value;
+                                       } else if (key == X_("codec_long_name")) {
+                                               if (!as.name.empty()) as.name += " ";
+                                               as.name += value;
+                                       } else if (key == X_("codec_name")) {
+                                               if (!as.name.empty()) as.name += " ";
+                                               as.name += value;
+                                       } else if (key == X_("sample_fmt")) {
+                                               if (!as.name.empty()) as.name += " ";
+                                               as.name += "FMT:" + value;
+                                       } else if (key == X_("sample_rate")) {
+                                               if (!as.name.empty()) as.name += " ";
+                                               as.name += "SR:" + value;
+                                       }
 
-                               pos = i->at(13).find_first_of(':');
-                               m_aspect = 0;
-                               if (pos != std::string::npos && atof(i->at(13).substr(pos+1).c_str()) != 0) {
-                                       m_aspect = atof(i->at(13).substr(0, pos).c_str()) / atof(i->at(13).substr(pos+1).c_str());
                                }
-                               if (m_aspect == 0) {
-                                       m_aspect = (double)m_width / (double)m_height;
-                               }
-
-                               int h,m,s; char f[7];
-                               if (sscanf(i->at(17).c_str(), "%d:%d:%d:%s",&h,&m,&s,f) == 4) {
-                                       m_duration = (ARDOUR::framecnt_t) floor(m_fps * (
-                                                       h * 3600.0
-                                               + m * 60.0
-                                               + s * 1.0
-                                               + atoi(f) / pow(10, strlen(f))
-                                       ));
-                               } else if (atof(i->at(23).c_str()) != 0) {
-                                       m_duration = atof(i->at(23).c_str());
-                               } else {
-                                       m_duration = atof(i->at(24).c_str()) * m_fps;
-                               }
-
-                       } else if (i->at(5) == X_("audio")) { /* new ffprobe */
-                               AudioStream as;
-                               as.name = i->at(3) + " " + i->at(2) + " " + i->at(9) + " " + i->at(10);
-                               as.stream_id  = i->at(1);
-                               as.channels   = atoi(i->at(11).c_str());
                                m_audio.push_back(as);
                        }
                }
@@ -241,7 +228,7 @@ TranscodeFfmpeg::probe ()
        while (ffcmd && --timeout) usleep (1000); // wait until 'ffprobe' terminated.
        if (timeout == 0) return false;
 
-#if 0 /* DEBUG */
+#if 1 /* DEBUG */
        printf("FPS: %f\n", m_fps);
        printf("Duration: %lu frames\n",(unsigned long)m_duration);
        printf("W/H: %ix%i\n",m_width, m_height);