diff options
-rw-r--r-- | gnuradio-core/src/lib/io/gr_file_meta_sink.cc | 58 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_file_meta_sink.h | 15 | ||||
-rw-r--r-- | gnuradio-core/src/lib/io/gr_file_meta_sink.i | 4 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/parse_file_metadata.py | 24 | ||||
-rw-r--r-- | gr-utils/src/python/gr_read_file_metadata | 20 |
5 files changed, 95 insertions, 26 deletions
diff --git a/gnuradio-core/src/lib/io/gr_file_meta_sink.cc b/gnuradio-core/src/lib/io/gr_file_meta_sink.cc index 9d092d79fa..401d8299d5 100644 --- a/gnuradio-core/src/lib/io/gr_file_meta_sink.cc +++ b/gnuradio-core/src/lib/io/gr_file_meta_sink.cc @@ -60,26 +60,43 @@ gr_file_meta_sink::gr_file_meta_sink(size_t itemsize, const char *filename, pmt_t timestamp = pmt_make_tuple(pmt_from_uint64(0), pmt_from_double(0)); + // handle extra dictionary + d_extra = pmt_make_dict(); + if(extra_dict.size() > 0) { + pmt_t extras = pmt_deserialize_str(extra_dict); + pmt_t keys = pmt_dict_keys(extras); + pmt_t vals = pmt_dict_values(extras); + size_t nitems = pmt_length(keys); + for(size_t i = 0; i < nitems; i++) { + d_extra = pmt_dict_add(d_extra, + pmt_nth(i, keys), + pmt_nth(i, vals)); + } + } + + d_extra_size = pmt_serialize_str(d_extra).size(); + d_header = pmt_make_dict(); d_header = pmt_dict_add(d_header, mp("rx_rate"), mp(samp_rate)); d_header = pmt_dict_add(d_header, mp("rx_time"), timestamp); d_header = pmt_dict_add(d_header, mp("type"), pmt_from_long(type)); d_header = pmt_dict_add(d_header, mp("cplx"), complex ? PMT_T : PMT_F); - d_header = pmt_dict_add(d_header, mp("strt"), pmt_from_uint64(HEADER_SIZE)); + d_header = pmt_dict_add(d_header, mp("strt"), pmt_from_uint64(HEADER_SIZE+d_extra_size)); d_header = pmt_dict_add(d_header, mp("size"), pmt_from_uint64(0)); - // handle extra dictionary - write_header(d_header); + write_header(d_header, d_extra); } void -gr_file_meta_sink::write_header(pmt_t header) +gr_file_meta_sink::write_header(pmt_t header, pmt_t extra) { do_update(); std::string header_str = pmt_serialize_str(header); - if(header_str.size() != HEADER_SIZE) - throw std::runtime_error("file_meta_sink: header is wrong size.\n"); + std::string extra_str = pmt_serialize_str(extra); + + if((header_str.size() != HEADER_SIZE) && (extra_str.size() != d_extra_size)) + throw std::runtime_error("file_meta_sink: header or extras is wrong size.\n"); size_t nwritten = 0; while(nwritten < header_str.size()) { @@ -91,6 +108,17 @@ gr_file_meta_sink::write_header(pmt_t header) throw std::runtime_error("file_meta_sink: error writing header to file.\n"); } } + + nwritten = 0; + while(nwritten < extra_str.size()) { + std::string sub = extra_str.substr(nwritten); + int count = fwrite(sub.c_str(), sizeof(char), sub.size(), d_fp); + nwritten += count; + if((count == 0) && (ferror(d_fp))) { + fclose(d_fp); + throw std::runtime_error("file_meta_sink: error writing extra to file.\n"); + } + } } bool @@ -107,6 +135,10 @@ gr_file_meta_sink::update_header(pmt_t key, pmt_t value) d_header = pmt_dict_add(d_header, key, value); return true; } + else if(pmt_dict_has_key(d_extra, key)) { + d_extra = pmt_dict_add(d_extra, key, value); + return true; + } else { return false; } @@ -118,7 +150,7 @@ gr_file_meta_sink::get_last_header_loc() uint64_t loc = 0; pmt_t v = pmt_dict_ref(d_header, mp("strt"), PMT_NIL); if(!pmt_eq(v, PMT_NIL)) - loc = pmt_to_uint64(v) - HEADER_SIZE; + loc = pmt_to_uint64(v) - (HEADER_SIZE+d_extra_size); return loc; } @@ -135,7 +167,7 @@ gr_file_meta_sink::~gr_file_meta_sink() //std::cerr << " Segment Size: " << seg_size << std::endl; if(update_header(mp("size"), s)) { fseek(d_fp, loc, SEEK_SET); - write_header(d_header); + write_header(d_header, d_extra); } } @@ -164,7 +196,7 @@ gr_file_meta_sink::work(int noutput_items, if(itr->offset == 0) { if(update_header(itr->key, itr->value)) { fseek(d_fp, 0, SEEK_SET); - write_header(d_header); + write_header(d_header, d_extra); } } else { @@ -178,7 +210,7 @@ gr_file_meta_sink::work(int noutput_items, //std::cerr << " segment size is: " << seg_size << std::endl; if(update_header(mp("size"), s)) { fseek(d_fp, loc, SEEK_SET); - write_header(d_header); + write_header(d_header, d_extra); } if(update_header(itr->key, itr->value)) { @@ -192,14 +224,14 @@ gr_file_meta_sink::work(int noutput_items, // of creating a new header per tag. uint64_t seg_start = loc; if(seg_size != 0) - seg_start += HEADER_SIZE + seg_size; - pmt_t s = pmt_from_uint64(seg_start + HEADER_SIZE); + seg_start += HEADER_SIZE + d_extra_size + seg_size + 1; + pmt_t s = pmt_from_uint64(seg_start + HEADER_SIZE + d_extra_size); if(update_header(mp("strt"), s)) { //std::cerr << "Adding new header" << std::endl; //std::cerr << " new header start at: " << seg_start-HEADER_SIZE << std::endl; //std::cerr << " new seg start at: " << seg_start << std::endl; fseek(d_fp, seg_start, SEEK_SET); - write_header(d_header); + write_header(d_header, d_extra); } } } diff --git a/gnuradio-core/src/lib/io/gr_file_meta_sink.h b/gnuradio-core/src/lib/io/gr_file_meta_sink.h index c0f30bdc08..9ba4878d17 100644 --- a/gnuradio-core/src/lib/io/gr_file_meta_sink.h +++ b/gnuradio-core/src/lib/io/gr_file_meta_sink.h @@ -46,8 +46,8 @@ typedef boost::shared_ptr<gr_file_meta_sink> gr_file_meta_sink_sptr; GR_CORE_API gr_file_meta_sink_sptr gr_make_file_meta_sink(size_t itemsize, const char *filename, - double samp_rate, double relative_rate, - gr_file_types type, bool complex, + double samp_rate=1, double relative_rate=1, + gr_file_types type=GR_FILE_FLOAT, bool complex=true, const std::string &extra_dict=""); /*! @@ -100,15 +100,16 @@ class GR_CORE_API gr_file_meta_sink : public gr_sync_block, public gr_file_sink_ double d_relative_rate; uint64_t d_total_seg_size; pmt_t d_header; - pmt_t d_extra_dict; + pmt_t d_extra; + size_t d_extra_size; protected: gr_file_meta_sink(size_t itemsize, const char *filename, - double samp_rate, double relative_rate, - gr_file_types type, bool complex, - const std::string &extra_dict); + double samp_rate=1, double relative_rate=1, + gr_file_types type=GR_FILE_FLOAT, bool complex=true, + const std::string &extra_dict=""); - void write_header(pmt_t header); + void write_header(pmt_t header, pmt_t extra); bool update_header(pmt_t key, pmt_t value); uint64_t get_last_header_loc(); diff --git a/gnuradio-core/src/lib/io/gr_file_meta_sink.i b/gnuradio-core/src/lib/io/gr_file_meta_sink.i index 7d90ca3049..b58a519cec 100644 --- a/gnuradio-core/src/lib/io/gr_file_meta_sink.i +++ b/gnuradio-core/src/lib/io/gr_file_meta_sink.i @@ -35,8 +35,8 @@ enum gr_file_types { gr_file_meta_sink_sptr gr_make_file_meta_sink(size_t itemsize, const char *filename, - double samp_rate, double relative_rate, - gr_file_types type, bool complex, + double samp_rate=1, double relative_rate=1, + gr_file_types type=GR_FILE_FLOAT, bool complex=true, const std::string & extra_dict=""); class gr_file_meta_sink : public gr_sync_block, public gr_file_sink_base diff --git a/gnuradio-core/src/python/gnuradio/parse_file_metadata.py b/gnuradio-core/src/python/gnuradio/parse_file_metadata.py index cff7566e41..c8a9fbde10 100644 --- a/gnuradio-core/src/python/gnuradio/parse_file_metadata.py +++ b/gnuradio-core/src/python/gnuradio/parse_file_metadata.py @@ -112,10 +112,12 @@ def parse_header(p, hdr_start, VERBOSE=False): r = gr.pmt_dict_ref(p, gr.pmt_string_to_symbol("strt"), dump) seg_start = gr.pmt_to_uint64(r) info["strt"] = seg_start + info["extra_len"] = seg_start - hdr_start - HEADER_LENGTH + info["has_extra"] = info["extra_len"] > 0 if(VERBOSE): print "Segment Start: {0} bytes".format(seg_start) - print "Header Length: {0}".format((seg_start-hdr_start)) - print "Extra Header? {0}".format((seg_start-hdr_start) > HEADER_LENGTH) + print "Extra Length: {0}".format((info["extra_len"])) + print "Extra Header? {0}".format(info["has_extra"]) else: sys.stderr.write("Could not find key 'strt': invalid or corrupt data file.\n") sys.exit(1) @@ -141,3 +143,21 @@ def parse_header(p, hdr_start, VERBOSE=False): sys.exit(1) return info + +# IF THERE IS EXTRA DATA, PULL OUT THE DICTIONARY AND PARSE IT +def parse_extra_dict(p, info, VERBOSE=False): + if(gr.pmt_is_dict(p) is False): + sys.stderr.write("Extra header is not a PMT dictionary: invalid or corrupt data file.\n") + sys.exit(1) + + items = gr.pmt_dict_items(p) + nitems = gr.pmt_length(items) + for i in xrange(nitems): + item = gr.pmt_nth(i, items) + key = gr.pmt_symbol_to_string(gr.pmt_car(item)) + val = gr.pmt_to_double(gr.pmt_cdr(item)) + info[key] = val + if(VERBOSE): + print "{0}: {1}".format(key, val) + + return info diff --git a/gr-utils/src/python/gr_read_file_metadata b/gr-utils/src/python/gr_read_file_metadata index 47109aead2..850c29ee7b 100644 --- a/gr-utils/src/python/gr_read_file_metadata +++ b/gr-utils/src/python/gr_read_file_metadata @@ -29,6 +29,7 @@ from gnuradio import parse_file_metadata def main(filename): handle = open(filename, "rb") + nheaders = 0 nread = 0 while(True): # read out next header bytes @@ -45,12 +46,27 @@ def main(filename): sys.exit(1) #gr.pmt_print(header) + print "HEADER {0}".format(nheaders) info = parse_file_metadata.parse_header(header, hdr_start, True) - print "\n\n" - nread += info['nbytes'] + parse_file_metadata.HEADER_LENGTH + if(info["extra_len"] > 0): + extra_str = handle.read(info["extra_len"]) + if(len(extra_str) == 0): + break + + try: + extra = gr.pmt_deserialize_str(extra_str) + except RuntimeError: + sys.stderr.write("Could not deserialize extras: invalid or corrupt data file.\n") + sys.exit(1) + print "\nExtra Header:" + extra_info = parse_file_metadata.parse_extra_dict(extra, info, True) + + nheaders += 1 + nread += info['nbytes'] + parse_file_metadata.HEADER_LENGTH + info["extra_len"] + 1 handle.seek(nread, 0) + print "\n\n" if __name__ == "__main__": usage="%prog: [options] filename" |