winlin

fix bug of flv parser, librtmp amf0 library

@@ -618,6 +618,14 @@ class RESTServers(object): @@ -618,6 +618,14 @@ class RESTServers(object):
618 "stream7": "http://demo.chnvideo.com:8085/api/v1/servers?id=ingest&action=hls&device_id=chnvideo-meiyi-cubieboard&stream=live/stream7" 618 "stream7": "http://demo.chnvideo.com:8085/api/v1/servers?id=ingest&action=hls&device_id=chnvideo-meiyi-cubieboard&stream=live/stream7"
619 } 619 }
620 }, 620 },
  621 + "meiyi-house": {
  622 + "rtmp": {
  623 + "livesteam": "http://demo.chnvideo.com:8085/api/v1/servers?id=ingest&action=rtmp&device_id=chnvideo-meiyi-cubieboard-house&stream=live/livestream"
  624 + },
  625 + "hls": {
  626 + "livesteam": "http://demo.chnvideo.com:8085/api/v1/servers?id=ingest&action=hls&device_id=chnvideo-meiyi-cubieboard-house&stream=live/livestream"
  627 + }
  628 + },
621 "meiyi-bk": { 629 "meiyi-bk": {
622 "rtmp": { 630 "rtmp": {
623 "livesteam": "http://demo.chnvideo.com:8085/api/v1/servers?id=ingest&action=rtmp&device_id=chnvideo-meiyi-cubieboard-bk&stream=live/livestream", 631 "livesteam": "http://demo.chnvideo.com:8085/api/v1/servers?id=ingest&action=rtmp&device_id=chnvideo-meiyi-cubieboard-bk&stream=live/livestream",
  1 +/*
  2 +The MIT License (MIT)
  3 +
  4 +Copyright (c) 2013-2014 winlin
  5 +
  6 +Permission is hereby granted, free of charge, to any person obtaining a copy of
  7 +this software and associated documentation files (the "Software"), to deal in
  8 +the Software without restriction, including without limitation the rights to
  9 +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  10 +the Software, and to permit persons to whom the Software is furnished to do so,
  11 +subject to the following conditions:
  12 +
  13 +The above copyright notice and this permission notice shall be included in all
  14 +copies or substantial portions of the Software.
  15 +
  16 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  18 +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  19 +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  20 +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21 +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22 +*/
  23 +/**
  24 +gcc srs_ingest_flv.c ../../objs/lib/srs_librtmp.a -g -O0 -lstdc++ -o srs_ingest_flv
  25 +*/
  26 +
  27 +#include <stdio.h>
  28 +#include <stdlib.h>
  29 +#include <unistd.h>
  30 +
  31 +#include <sys/types.h>
  32 +#include <sys/stat.h>
  33 +#include <fcntl.h>
  34 +
  35 +#include "../../objs/include/srs_librtmp.h"
  36 +#include "srs_research_public.h"
  37 +#include "srs_flv_codec.h"
  38 +
  39 +int parse_flv(int flv_fd);
  40 +int main(int argc, char** argv)
  41 +{
  42 + int ret = 0;
  43 +
  44 + // user options.
  45 + char* in_flv_file;
  46 + // flv handler
  47 + int flv_fd;
  48 +
  49 + if (argc <= 1) {
  50 + printf("parse and show flv file detail\n"
  51 + "Usage: %s in_flv_file\n"
  52 + " in_flv_file flv file to parse and show.\n"
  53 + "For example:\n"
  54 + " %s ../../doc/source.200kbps.768x320.flv\n",
  55 + argv[0]);
  56 + ret = 1;
  57 + exit(ret);
  58 + return ret;
  59 + }
  60 +
  61 + in_flv_file = argv[1];
  62 +
  63 + trace("parse and show flv file detail.");
  64 + trace("srs(simple-rtmp-server) client librtmp library.");
  65 + trace("version: %d.%d.%d", srs_version_major(), srs_version_minor(), srs_version_revision());
  66 + trace("input: %s", in_flv_file);
  67 +
  68 + flv_fd = open_flv_file(in_flv_file);
  69 + if (flv_fd <= 0) {
  70 + ret = 2;
  71 + trace("open flv file failed. ret=%d", ret);
  72 + return ret;
  73 + }
  74 +
  75 + ret = parse_flv(flv_fd);
  76 + close_flv_file(flv_fd);
  77 +
  78 + return ret;
  79 +}
  80 +
  81 +int parse_audio_data(char* data, int size)
  82 +{
  83 + int ret = 0;
  84 + return ret;
  85 +}
  86 +
  87 +int parse_video_data(char* data, int size)
  88 +{
  89 + int ret = 0;
  90 + return ret;
  91 +}
  92 +
  93 +void digit_to_char(char* src, int ssize, char* dst, int dsize)
  94 +{
  95 + int i, j;
  96 + char v;
  97 +
  98 + for (i = 0, j = 0; i < ssize && j < dsize; i++) {
  99 + if (j >= dsize) {
  100 + break;
  101 + }
  102 + v = (src[i] >> 4) & 0x0F;
  103 + if (v < 10) {
  104 + dst[j++] = '0' + v;
  105 + } else {
  106 + dst[j++] = 'A' + (v - 10);
  107 + }
  108 +
  109 + if (j >= dsize) {
  110 + break;
  111 + }
  112 + v = src[i] & 0x0F;
  113 + if (v < 10) {
  114 + dst[j++] = '0' + v;
  115 + } else {
  116 + dst[j++] = 'A' + (v - 10);
  117 + }
  118 +
  119 + if (j >= dsize) {
  120 + break;
  121 + }
  122 + if (i < ssize - 1) {
  123 + dst[j++] = ' ';
  124 + }
  125 + }
  126 +}
  127 +
  128 +int parse_bytes(char* data, int size, char* hbuf, int hsize, char* tbuf, int tsize, int print_size)
  129 +{
  130 + memset(hbuf, 0, hsize);
  131 + memset(tbuf, 0, tsize);
  132 + if (size > print_size * 2) {
  133 + digit_to_char(data, size, hbuf, hsize - 1);
  134 + digit_to_char(data + size - print_size, size, tbuf, tsize - 1);
  135 + }
  136 +}
  137 +
  138 +int parse_script_data(char* data, int size)
  139 +{
  140 + int ret = 0;
  141 +
  142 + char hbuf[48];
  143 + char tbuf[48];
  144 + parse_bytes(data, size, hbuf, sizeof(hbuf), tbuf, sizeof(tbuf), 16);
  145 +
  146 + srs_amf0_t amf0 = srs_amf0_parse(data, size);
  147 + if (amf0 == NULL) {
  148 + trace("invalid amf0 data.");
  149 + return -1;
  150 + }
  151 +
  152 + trace("details:\n"
  153 + "[+00, +15] %s\n[-15, EOF] %s",
  154 + hbuf, tbuf);
  155 +
  156 + return ret;
  157 +}
  158 +
  159 +int parse_flv(int flv_fd)
  160 +{
  161 + int ret = 0;
  162 +
  163 + if ((ret = flv_open_ic(flv_fd)) != 0) {
  164 + return ret;
  165 + }
  166 +
  167 + // packet data
  168 + int type, size;
  169 + u_int32_t timestamp = 0;
  170 + char* data = NULL;
  171 +
  172 + trace("start parse flv");
  173 + for (;;) {
  174 + if ((ret = flv_read_packet(flv_fd, &type, &timestamp, &data, &size)) != 0) {
  175 + if (ret == ERROR_FLV_CODEC_EOF) {
  176 + trace("parse completed.");
  177 + return 0;
  178 + }
  179 + trace("irtmp get packet failed. ret=%d", ret);
  180 + return ret;
  181 + }
  182 + trace("flv got packet: type=%s, time=%d, size=%d", srs_type2string(type), timestamp, size);
  183 +
  184 + // data tag
  185 + if (type == SRS_RTMP_TYPE_AUDIO) {
  186 + if ((ret = parse_audio_data(data, size)) != 0) {
  187 + return ret;
  188 + }
  189 + } else if (type == SRS_RTMP_TYPE_VIDEO) {
  190 + if ((ret = parse_video_data(data, size)) != 0) {
  191 + return ret;
  192 + }
  193 + } else {
  194 + if ((ret = parse_script_data(data, size)) != 0) {
  195 + return ret;
  196 + }
  197 + }
  198 +
  199 + free(data);
  200 + }
  201 +
  202 + return ret;
  203 +}
@@ -435,6 +435,42 @@ srs_amf0_t srs_amf0_parse(char* data, int size) @@ -435,6 +435,42 @@ srs_amf0_t srs_amf0_parse(char* data, int size)
435 return amf0; 435 return amf0;
436 } 436 }
437 437
  438 +amf0_bool srs_amf0_is_string(srs_amf0_t amf0)
  439 +{
  440 + SrsAmf0Any* any = (SrsAmf0Any*)amf0;
  441 + return any->is_string();
  442 +}
  443 +
  444 +amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0)
  445 +{
  446 + SrsAmf0Any* any = (SrsAmf0Any*)amf0;
  447 + return any->is_boolean();
  448 +}
  449 +
  450 +amf0_bool srs_amf0_is_number(srs_amf0_t amf0)
  451 +{
  452 + SrsAmf0Any* any = (SrsAmf0Any*)amf0;
  453 + return any->is_number();
  454 +}
  455 +
  456 +amf0_bool srs_amf0_is_null(srs_amf0_t amf0)
  457 +{
  458 + SrsAmf0Any* any = (SrsAmf0Any*)amf0;
  459 + return any->is_null();
  460 +}
  461 +
  462 +amf0_bool srs_amf0_is_object(srs_amf0_t amf0)
  463 +{
  464 + SrsAmf0Any* any = (SrsAmf0Any*)amf0;
  465 + return any->is_object();
  466 +}
  467 +
  468 +amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0)
  469 +{
  470 + SrsAmf0Any* any = (SrsAmf0Any*)amf0;
  471 + return any->is_ecma_array();
  472 +}
  473 +
438 #ifdef __cplusplus 474 #ifdef __cplusplus
439 } 475 }
440 #endif 476 #endif
@@ -162,9 +162,21 @@ int64_t srs_get_time_ms(); @@ -162,9 +162,21 @@ int64_t srs_get_time_ms();
162 /** 162 /**
163 * amf0 codec 163 * amf0 codec
164 */ 164 */
165 -// the output handler. 165 +/* the output handler. */
166 typedef void* srs_amf0_t; 166 typedef void* srs_amf0_t;
167 -srs_amf0_t srs_amf0_parse(char* data, int size); 167 +typedef int amf0_bool;
  168 +extern srs_amf0_t srs_amf0_parse(char* data, int size);
  169 +/* type detecter */
  170 +extern amf0_bool srs_amf0_is_string(srs_amf0_t amf0);
  171 +extern amf0_bool srs_amf0_is_boolean(srs_amf0_t amf0);
  172 +extern amf0_bool srs_amf0_is_number(srs_amf0_t amf0);
  173 +extern amf0_bool srs_amf0_is_null(srs_amf0_t amf0);
  174 +extern amf0_bool srs_amf0_is_object(srs_amf0_t amf0);
  175 +extern amf0_bool srs_amf0_is_ecma_array(srs_amf0_t amf0);
  176 +/* value converter */
  177 +/*const char* srs_amf0_to_string(srs_amf0_t amf0);
  178 +bool srs_amf0_to_boolean(srs_amf0_t amf0);
  179 +double srs_amf0_to_number(srs_amf0_t amf0);*/
168 180
169 #ifdef __cplusplus 181 #ifdef __cplusplus
170 } 182 }