diff --git a/lib/mirror_buffer.c b/lib/mirror_buffer.c index 2bbccda..b88fe24 100644 --- a/lib/mirror_buffer.c +++ b/lib/mirror_buffer.c @@ -28,7 +28,6 @@ #include #include -//#define DUMP_KEI_IV struct mirror_buffer_s { logger_t *logger; aes_ctx_t *aes_ctx; @@ -66,13 +65,6 @@ mirror_buffer_init_aes(mirror_buffer_t *mirror_buffer, const uint64_t *streamCon // Need to be initialized externally mirror_buffer->aes_ctx = aes_ctr_init(aeskey_video, aesiv_video); - -#ifdef DUMP_KEI_IV - FILE* keyfile = fopen("/sdcard/111.keyiv", "wb"); - fwrite(aeskey_video, 16, 1, keyfile); - fwrite(aesiv_video, 16, 1, keyfile); - fclose(keyfile); -#endif } mirror_buffer_t * diff --git a/lib/raop_buffer.c b/lib/raop_buffer.c index e18ca20..0dd0183 100644 --- a/lib/raop_buffer.c +++ b/lib/raop_buffer.c @@ -79,14 +79,6 @@ raop_buffer_init(logger_t *logger, // Need to be initialized internally raop_buffer->aes_ctx = aes_cbc_init(aeskey, aesiv, AES_DECRYPT); -#ifdef DUMP_AUDIO - if (file_keyiv != NULL) { - fwrite(aeskey, 16, 1, file_keyiv); - fwrite(aesiv, 16, 1, file_keyiv); - fclose(file_keyiv); - } -#endif - for (int i = 0; i < RAOP_BUFFER_LENGTH; i++) { raop_buffer_entry_t *entry = &raop_buffer->entries[i]; entry->payload_data = NULL; @@ -113,15 +105,6 @@ raop_buffer_destroy(raop_buffer_t *raop_buffer) free(raop_buffer); } -#ifdef DUMP_AUDIO - if (file_aac != NULL) { - fclose(file_aac); - } - if (file_source != NULL) { - fclose(file_source); - } -#endif - } static short @@ -130,32 +113,11 @@ seqnum_cmp(unsigned short s1, unsigned short s2) return (s1 - s2); } -//#define DUMP_AUDIO - -#ifdef DUMP_AUDIO -static FILE* file_aac = NULL; -static FILE* file_source = NULL; -static FILE* file_keyiv = NULL; -#endif - - int raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned char* output, unsigned int payload_size, unsigned int *outputlen) { assert(raop_buffer); int encryptedlen; -#ifdef DUMP_AUDIO - if (file_aac == NULL) { - file_aac = fopen("/home/pi/Airplay.aac", "wb"); - file_source = fopen("/home/pi/Airplay.source", "wb"); - file_keyiv = fopen("/home/pi/Airplay.keyiv", "wb"); - } - // Undecrypted file - if (file_source != NULL) { - fwrite(&data[12], payloadsize, 1, file_source); - } -#endif - if (DECRYPTION_TEST) { char *str = utils_data_to_string(data,12,12); logger_log(raop_buffer->logger, LOGGER_INFO, "encrypted 12 byte header %s", str); @@ -199,13 +161,6 @@ raop_buffer_decrypt(raop_buffer_t *raop_buffer, unsigned char *data, unsigned ch free(str); } } -#ifdef DUMP_AUDIO - // Decrypted file - if (file_aac != NULL) { - fwrite(output, payloadsize, 1, file_aac); - } -#endif - return 1; } diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index 0415027..75349c5 100644 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -104,12 +104,6 @@ struct raop_rtp_mirror_s { /* switch for displaying client FPS data */ uint8_t show_client_FPS_data; - - /* SPS and PPS */ - int sps_pps_len; - unsigned char* sps_pps; - bool sps_pps_waiting; - }; static int @@ -154,9 +148,6 @@ raop_rtp_mirror_t *raop_rtp_mirror_init(logger_t *logger, raop_callbacks_t *call } raop_rtp_mirror->logger = logger; raop_rtp_mirror->ntp = ntp; - raop_rtp_mirror->sps_pps_len = 0; - raop_rtp_mirror->sps_pps = NULL; - raop_rtp_mirror->sps_pps_waiting = false; memcpy(&raop_rtp_mirror->callbacks, callbacks, sizeof(raop_callbacks_t)); raop_rtp_mirror->buffer = mirror_buffer_init(logger, aeskey); @@ -182,8 +173,6 @@ raop_rtp_init_mirror_aes(raop_rtp_mirror_t *raop_rtp_mirror, uint64_t *streamCon mirror_buffer_init_aes(raop_rtp_mirror->buffer, streamConnectionID); } -//#define DUMP_H264 - #define RAOP_PACKET_LEN 32768 /** * Mirror @@ -197,6 +186,9 @@ raop_rtp_mirror_thread(void *arg) int stream_fd = -1; unsigned char packet[128]; memset(packet, 0 , 128); + unsigned char* sps_pps = NULL; + bool prepend_sps_pps = false; + int sps_pps_len = 0; unsigned char* payload = NULL; unsigned int readstart = 0; bool conn_reset = false; @@ -206,13 +198,6 @@ raop_rtp_mirror_thread(void *arg) uint64_t ntp_timestamp_local = 0; unsigned char nal_start_code[4] = { 0x00, 0x00, 0x00, 0x01 }; bool logger_debug = (logger_get_level(raop_rtp_mirror->logger) >= LOGGER_DEBUG); -#ifdef DUMP_H264 - // C decrypted - FILE* file = fopen("/home/pi/Airplay.h264", "wb"); - // Encrypted source file - FILE* file_source = fopen("/home/pi/Airplay.source", "wb"); - FILE* file_len = fopen("/home/pi/Airplay.len", "wb"); -#endif while (1) { fd_set rfds; @@ -257,7 +242,8 @@ raop_rtp_mirror_thread(void *arg) saddrlen = sizeof(saddr); stream_fd = accept(raop_rtp_mirror->mirror_data_sock, (struct sockaddr *)&saddr, &saddrlen); if (stream_fd == -1) { - logger_log(raop_rtp_mirror->logger, LOGGER_ERR, "raop_rtp_mirror error in accept %d %s", errno, strerror(errno)); + logger_log(raop_rtp_mirror->logger, LOGGER_ERR, + "raop_rtp_mirror error in accept %d %s", errno, strerror(errno)); break; } @@ -266,26 +252,31 @@ raop_rtp_mirror_thread(void *arg) tv.tv_sec = 0; tv.tv_usec = 5000; if (setsockopt(stream_fd, SOL_SOCKET, SO_RCVTIMEO, CAST &tv, sizeof(tv)) < 0) { - logger_log(raop_rtp_mirror->logger, LOGGER_ERR, "raop_rtp_mirror could not set stream socket timeout %d %s", errno, strerror(errno)); + logger_log(raop_rtp_mirror->logger, LOGGER_ERR, + "raop_rtp_mirror could not set stream socket timeout %d %s", errno, strerror(errno)); break; } int option; option = 1; if (setsockopt(stream_fd, SOL_SOCKET, SO_KEEPALIVE, CAST &option, sizeof(option)) < 0) { - logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "raop_rtp_mirror could not set stream socket keepalive %d %s", errno, strerror(errno)); + logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, + "raop_rtp_mirror could not set stream socket keepalive %d %s", errno, strerror(errno)); } option = 60; if (setsockopt(stream_fd, SOL_TCP, TCP_KEEPIDLE, CAST &option, sizeof(option)) < 0) { - logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "raop_rtp_mirror could not set stream socket keepalive time %d %s", errno, strerror(errno)); + logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, + "raop_rtp_mirror could not set stream socket keepalive time %d %s", errno, strerror(errno)); } option = 10; if (setsockopt(stream_fd, SOL_TCP, TCP_KEEPINTVL, CAST &option, sizeof(option)) < 0) { - logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "raop_rtp_mirror could not set stream socket keepalive interval %d %s", errno, strerror(errno)); + logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, + "raop_rtp_mirror could not set stream socket keepalive interval %d %s", errno, strerror(errno)); } option = 6; if (setsockopt(stream_fd, SOL_TCP, TCP_KEEPCNT, CAST &option, sizeof(option)) < 0) { - logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "raop_rtp_mirror could not set stream socket keepalive probes %d %s", errno, strerror(errno)); + logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, + "raop_rtp_mirror could not set stream socket keepalive probes %d %s", errno, strerror(errno)); } readstart = 0; } @@ -301,13 +292,15 @@ raop_rtp_mirror_thread(void *arg) } if (payload == NULL && ret == 0) { - logger_log(raop_rtp_mirror->logger, LOGGER_ERR, "raop_rtp_mirror tcp socket is closed, got %d bytes of 128 byte header",readstart); + logger_log(raop_rtp_mirror->logger, LOGGER_ERR, + "raop_rtp_mirror tcp socket is closed, got %d bytes of 128 byte header",readstart); FD_CLR(stream_fd, &rfds); stream_fd = -1; continue; } else if (payload == NULL && ret == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK) continue; // Timeouts can happen even if the connection is fine - logger_log(raop_rtp_mirror->logger, LOGGER_ERR, "raop_rtp_mirror error in header recv: %d %s", errno, strerror(errno)); + logger_log(raop_rtp_mirror->logger, LOGGER_ERR, + "raop_rtp_mirror error in header recv: %d %s", errno, strerror(errno)); if (errno == ECONNRESET) conn_reset = true;; break; } @@ -324,26 +317,28 @@ raop_rtp_mirror_thread(void *arg) } ntp_timestamp_raw = byteutils_get_long(packet, 8); ntp_timestamp_remote = raop_ntp_timestamp_to_nano_seconds(ntp_timestamp_raw, false); - - /* packet[4] appears to have one of three possible values: * - * 0x00 : encrypted packet * - * 0x01 : unencrypted packet with a SPS and a PPS NAL, sent initially, and also when * - * a change in video format (e.g., width, height) subsequently occurs * - * 0x05 : unencrypted packet with a "streaming report", sent once per second */ - /* encrypted packets have packet[5] = 0x00 or 0x10, and packet[6]= packet[7] = 0x00; * - * encrypted packets immediately following an unencrypted SPS/PPS packet appear to * - * be the only ones with packet[5] = 0x10, and almost always have packet[5] = 0x10, * - * but occasionally have packet[5] = 0x00. */ + /* packet[4] + packet[5] identify the payload type: values seen are: * + * 0x00 0x00: encrypted packet containing a non-IDR type 1 VCL NAL unit * + * 0x00 0x10: encrypted packet containing an IDR type 5 VCL NAL unit * + * 0x01 0x00 unencrypted packet containing a type 7 SPS NAL + a type 8 PPS NAL unit * + * 0x05 0x00 unencrypted packet with a "streaming report", sent once per second. */ - /* unencrypted SPS/PPS packets have packet[4:7] = 0x01 0x00 (0x16 or 0x56) 0x01 * - * they are followed by an encrypted packet with the same timestamp in packet[8:15] */ + /* packet[6] + packet[7] may list a payload "option": values seen are: * + * 0x00 0x00 : encrypted and "streaming report" packets * + * 0x16 0x01 : seen in most unencrypted SPS+PPS packets * + * 0x56 0x01 : occasionally seen in unencrypted SPS+PPS packets (why different?) */ - /* "streaming report" packages have packet[4:7] = 0x05 0x00 0x00 0x00, and have no * - * timestamp in packet[8:15] */ + /* unencrypted packets with a SPS and a PPS NAL are sent initially, and also when a * + * change in video format (e.g. width, height) subsequently occurs. They seem always * + * to be followed by a packet with a type 5 encrypted IDR VCL NAL, with an identical * + * timestamp. On M1/M2 Mac clients, this type 5 NAL is prepended with a type 6 SEI * + * NAL unit. Here we prepend the SPS+PPS NALs to the next encrypted packet, which * + * always has the same timestamp, and is (almost?) always an IDR NAL unit. */ - //unsigned short payload_type = byteutils_get_short(packet, 4) & 0xff; - //unsigned short payload_option = byteutils_get_short(packet, 6); + /* Unencrypted SPS/PPS packets also have image-size data in (parts of) packet[16:127] */ + + /* "streaming report" packets have no timestamp in packet[8:15] */ if (payload == NULL) { payload = malloc(payload_size); @@ -387,33 +382,36 @@ raop_rtp_mirror_thread(void *arg) (double) ntp_timestamp_remote / SEC, packet_description); } -#ifdef DUMP_H264 - fwrite(payload, payload_size, 1, file_source); - fwrite(&readstart, sizeof(readstart), 1, file_len); -#endif unsigned char* payload_out; unsigned char* payload_decrypted; - if (!raop_rtp_mirror->sps_pps_waiting && packet[5] != 0x00) { - logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "unexpected: packet[5] = %2.2x, but not preceded by SPS+PPS packet", packet[5]); - } - /* if a previous unencrypted packet contains an SPS (type 7) and PPS (type 8) NAL which has not - * yet been sent, it should be prepended to the current NAL. In this case packet[5] is usually - * 0x10; however, the M1 Macs have increased the h264 level, and now the encrypted packet after the - * unencrypted SPS+PPS packet may contain a SEI (type 6) NAL prepended to the next VCL NAL, with - * packet[5] = 0x00. Now the flag raop_rtp_mirror->sps_pps_waiting = true will signal that a - * previous packet contained a SPS NAL + a PPS NAL, that has not yet been sent. This will trigger - * prepending it to the current NAL, and the sps_pps_waiting flag will be set to false after - * it has been prepended. It is not clear if the case packet[5] = 0x10 will occur when - * raop_rtp_mirror->sps_pps = false, but if it does, the current code will prepend the stored - * PPS + SPS NAL to the current encrypted NAL, and issue a warning message */ + /* + * nal_types:1 Coded non-partitioned slice of a non-IDR picture + * 5 Coded non-partitioned slice of an IDR picture + * 6 Supplemental enhancement information (SEI) + * 7 Sequence parameter set (SPS) + * 8 Picture parameter set (PPS) + * + * if a previous unencrypted packet contains an SPS (type 7) and PPS (type 8) NAL which has not + * yet been sent, it should be prepended to the current NAL. The M1 Macs have increased the h264 level, + * and now the first encrypted packet after the unencrypted SPS+PPS packet may also contain a SEI (type 6) NAL + * prepended to its VCL NAL. + * + * The flag prepend_sps_pps = true will signal that the previous packet contained a SPS NAL + a PPS NAL, + * that has not yet been sent. This will trigger prepending it to the current NAL, and the prepend_sps_pps + * flag will be set to false after it has been prepended. */ - bool prepend_sps_pps = (raop_rtp_mirror->sps_pps_waiting || packet[5] != 0x00); if (prepend_sps_pps) { - assert(raop_rtp_mirror->sps_pps); - payload_out = (unsigned char*) malloc(payload_size + raop_rtp_mirror->sps_pps_len); - payload_decrypted = payload_out + raop_rtp_mirror->sps_pps_len; - memcpy(payload_out, raop_rtp_mirror->sps_pps, raop_rtp_mirror->sps_pps_len); - raop_rtp_mirror->sps_pps_waiting = false; + assert(sps_pps); + payload_out = (unsigned char*) malloc(payload_size + sps_pps_len); + payload_decrypted = payload_out + sps_pps_len; + if (ntp_timestamp_raw != ntp_timestamp_nal) { + logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, + "raop_rtp_mirror: prepended sps_pps timestamp does not match timestamp of " + "video payload\n%llu\n%llu", ntp_timestamp_raw, ntp_timestamp_nal); + } + memcpy(payload_out, sps_pps, sps_pps_len); + free (sps_pps); + sps_pps = NULL; } else { payload_out = (unsigned char*) malloc(payload_size); payload_decrypted = payload_out; @@ -426,7 +424,6 @@ raop_rtp_mirror_thread(void *arg) bool valid_data = true; int nalu_size = 0; int nalus_count = 0; - int nalu_type; /* 0x01 non-IDR VCL, 0x05 IDR VCL, 0x06 SEI 0x07 SPS, 0x08 PPS */ while (nalu_size < payload_size) { int nc_len = byteutils_get_int_be(payload_decrypted, nalu_size); if (nc_len < 0 || nalu_size + 4 > payload_size) { @@ -436,22 +433,49 @@ raop_rtp_mirror_thread(void *arg) memcpy(payload_decrypted + nalu_size, nal_start_code, 4); nalu_size += 4; nalus_count++; - if (payload_decrypted[nalu_size] & 0x80) valid_data = false; /* first bit of h264 nalu MUST be 0 ("forbidden_zero_bit") */ - nalu_type = payload_decrypted[nalu_size] & 0x1f; - nalu_size += nc_len; - if (nalu_type != 1) { - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "nalu_type = %d, nalu_size = %d, processed bytes %d, payloadsize = %d nalus_count = %d", - nalu_type, nc_len, nalu_size, payload_size, nalus_count); + /* first bit of h264 nalu MUST be 0 ("forbidden_zero_bit") */ + if (payload_decrypted[nalu_size] & 0x80) { + valid_data = false; + break; } - } + int nalu_type = payload_decrypted[nalu_size] & 0x1f; + int ref_idc = (payload_decrypted[nalu_size] >> 5); + switch (nalu_type) { + case 5: /*IDR, slice_layer_without_partitioning */ + case 1: /*non-IDR, slice_layer_without_partitioning */ + break; + case 2: /* slice data partition A */ + case 3: /* slice data partition B */ + case 4: /* slice data partition C */ + logger_log(raop_rtp_mirror->logger, LOGGER_INFO, + "unexpected partitioned VCL NAL unit: nalu_type = %d, ref_idc = %d, nalu_size = %d," + "processed bytes %d, payloadsize = %d nalus_count = %d", + nalu_type, ref_idc, nc_len, nalu_size, payload_size, nalus_count); + break; + case 6: + if (logger_debug) { + char *str = utils_data_to_string(payload_decrypted + nalu_size, nc_len, 16); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror SEI NAL size = %d", nc_len); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, + "raop_rtp_mirror h264 Supplemental Enhancement Information:\n%s", str); + free(str); + } + break; + default: + logger_log(raop_rtp_mirror->logger, LOGGER_INFO, + "unexpected non-VCL NAL unit: nalu_type = %d, ref_idc = %d, nalu_size = %d," + "processed bytes %d, payloadsize = %d nalus_count = %d", + nalu_type, ref_idc, nc_len, nalu_size, payload_size, nalus_count); + break; + } + nalu_size += nc_len; + } if (nalu_size != payload_size) valid_data = false; if(!valid_data) { logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "nalu marked as invalid"); payload_out[0] = 1; /* mark video data as invalid h264 (failed decryption) */ } -#ifdef DUMP_H264 - fwrite(payload_decrypted, payload_size, 1, file); -#endif + payload_decrypted = NULL; h264_decode_struct h264_data; h264_data.ntp_time_local = ntp_timestamp_local; @@ -460,11 +484,9 @@ raop_rtp_mirror_thread(void *arg) h264_data.data_len = payload_size; h264_data.data = payload_out; if (prepend_sps_pps) { - h264_data.data_len += raop_rtp_mirror->sps_pps_len; + h264_data.data_len += sps_pps_len; h264_data.nal_count += 2; - if (ntp_timestamp_raw != ntp_timestamp_nal) { - logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "raop_rtp_mirror: prepended sps_pps timestamp does not match that of video payload"); - } + prepend_sps_pps = false; } raop_rtp_mirror->callbacks.video_process(raop_rtp_mirror->callbacks.cls, raop_rtp_mirror->ntp, &h264_data); free(payload_out); @@ -472,7 +494,8 @@ raop_rtp_mirror_thread(void *arg) case 0x01: // The information in the payload contains an SPS and a PPS NAL // The sps_pps is not encrypted - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "\nReceived unencryted codec packet from client: payload_size %d header %s ts_client = %8.6f", + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "\nReceived unencryted codec packet from client:" + " payload_size %d header %s ts_client = %8.6f", payload_size, packet_description, (double) ntp_timestamp_remote / SEC); if (payload_size == 0) { logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror, discard type 0x01 packet with no payload"); @@ -484,8 +507,8 @@ raop_rtp_mirror_thread(void *arg) float width_source = byteutils_get_float(packet, 40); float height_source = byteutils_get_float(packet, 44); if (width != width_source || height != height_source) { - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror: Unexpected : data %f, %f != width_source = %f, height_source = %f", - width, height, width_source, height_source); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror: Unexpected : data %f," + " %f != width_source = %f, height_source = %f", width, height, width_source, height_source); } width = byteutils_get_float(packet, 48); height = byteutils_get_float(packet, 52); @@ -505,15 +528,15 @@ raop_rtp_mirror_thread(void *arg) int data_size = 6; if (logger_debug) { char *str = utils_data_to_string(payload, data_size, 16); - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror: sps/pps header size = %d", data_size); - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror h264 sps/pps header:\n%s", str); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror: SPS+PPS header size = %d", data_size); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror h264 SPS+PPS header:\n%s", str); free(str); str = utils_data_to_string(sequence_parameter_set, sps_size,16); - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror sps size = %d", sps_size); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror SPS NAL size = %d", sps_size); logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror h264 Sequence Parameter Set:\n%s", str); free(str); str = utils_data_to_string(picture_parameter_set, pps_size, 16); - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror pps size = %d", pps_size); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror PPS NAL size = %d", pps_size); logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror h264 Picture Parameter Set:\n%s", str); free(str); } @@ -521,27 +544,25 @@ raop_rtp_mirror_thread(void *arg) if (data_size > 0 && logger_debug) { char *str = utils_data_to_string (picture_parameter_set + pps_size, data_size, 16); logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "remainder size = %d", data_size); - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "remainder of sps+pps packet:\n%s", str); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "remainder of SPS+PPS packet:\n%s", str); free(str); } else if (data_size < 0) { logger_log(raop_rtp_mirror->logger, LOGGER_ERR, " pps_sps error: packet remainder size = %d < 0", data_size); } // Copy the sps and pps into a buffer to prepend to the next NAL unit. - raop_rtp_mirror->sps_pps_len = sps_size + pps_size + 8; - if (raop_rtp_mirror->sps_pps) { - free(raop_rtp_mirror->sps_pps); + if (sps_pps) { + free(sps_pps); + sps_pps = NULL; } - raop_rtp_mirror->sps_pps = (unsigned char*) malloc(raop_rtp_mirror->sps_pps_len); - assert(raop_rtp_mirror->sps_pps); - memcpy(raop_rtp_mirror->sps_pps, nal_start_code, 4); - memcpy(raop_rtp_mirror->sps_pps + 4, sequence_parameter_set, sps_size); - memcpy(raop_rtp_mirror->sps_pps + sps_size + 4, nal_start_code, 4); - memcpy(raop_rtp_mirror->sps_pps + sps_size + 8, payload + sps_size + 11, pps_size); - raop_rtp_mirror->sps_pps_waiting = true; -#ifdef DUMP_H264 - fwrite(raop_rtp_mirror->sps_pps, raop_rtp_mirror->sps_pps_len, 1, file); -#endif + sps_pps_len = sps_size + pps_size + 8; + sps_pps = (unsigned char*) malloc(sps_pps_len); + assert(sps_pps); + memcpy(sps_pps, nal_start_code, 4); + memcpy(sps_pps + 4, sequence_parameter_set, sps_size); + memcpy(sps_pps + sps_size + 4, nal_start_code, 4); + memcpy(sps_pps + sps_size + 8, payload + sps_size + 11, pps_size); + prepend_sps_pps = true; // h264codec_t h264; // h264.version = payload[0]; @@ -560,8 +581,8 @@ raop_rtp_mirror_thread(void *arg) break; case 0x05: - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "\nReceived video streaming performance info packet from client: payload_size %d header %s ts_raw = %llu", - payload_size, packet_description, ntp_timestamp_raw); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "\nReceived video streaming performance info packet from client:" + " payload_size %d header %s ts_raw = %llu", payload_size, packet_description, ntp_timestamp_raw); /* payloads with packet[4] = 0x05 have no timestamp, and carry video info from the client as a binary plist * * Sometimes (e.g, when the client has a locked screen), there is a 25kB trailer attached to the packet. * * This 25000 Byte trailer with unidentified content seems to be the same data each time it is sent. */ @@ -576,7 +597,8 @@ raop_rtp_mirror_thread(void *arg) plist_size = payload_size - 25000; if (logger_debug) { char *str = utils_data_to_string(payload + plist_size, 16, 16); - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "video_info packet had 25kB trailer; first 16 bytes are:\n%s", str); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, + "video_info packet had 25kB trailer; first 16 bytes are:\n%s", str); free(str); } } @@ -592,8 +614,8 @@ raop_rtp_mirror_thread(void *arg) } break; default: - logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "\nReceived unexpected TCP packet from client, size %d, %s ts_raw = raw%llu", - payload_size, packet_description, ntp_timestamp_raw); + logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "\nReceived unexpected TCP packet from client, " + "size %d, %s ts_raw = raw%llu", payload_size, packet_description, ntp_timestamp_raw); break; } @@ -609,12 +631,6 @@ raop_rtp_mirror_thread(void *arg) closesocket(stream_fd); } -#ifdef DUMP_H264 - fclose(file); - fclose(file_source); - fclose(file_len); -#endif - // Ensure running reflects the actual state MUTEX_LOCK(raop_rtp_mirror->run_mutex); raop_rtp_mirror->running = false; @@ -649,7 +665,8 @@ raop_rtp_init_mirror_sockets(raop_rtp_mirror_t *raop_rtp_mirror, int use_ipv6) /* Set port values */ raop_rtp_mirror->mirror_data_lport = dport; - logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror local data port socket %d port TCP %d", dsock, dport); + logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror local data port socket %d port TCP %d", + dsock, dport); return 0; sockets_cleanup: @@ -658,7 +675,8 @@ raop_rtp_init_mirror_sockets(raop_rtp_mirror_t *raop_rtp_mirror, int use_ipv6) } void -raop_rtp_start_mirror(raop_rtp_mirror_t *raop_rtp_mirror, int use_udp, unsigned short *mirror_data_lport, uint8_t show_client_FPS_data) +raop_rtp_start_mirror(raop_rtp_mirror_t *raop_rtp_mirror, int use_udp, unsigned short *mirror_data_lport, + uint8_t show_client_FPS_data) { logger_log(raop_rtp_mirror->logger, LOGGER_INFO, "raop_rtp_mirror starting mirroring"); int use_ipv6 = 0; @@ -726,9 +744,6 @@ void raop_rtp_mirror_destroy(raop_rtp_mirror_t *raop_rtp_mirror) { raop_rtp_mirror_stop(raop_rtp_mirror); MUTEX_DESTROY(raop_rtp_mirror->run_mutex); mirror_buffer_destroy(raop_rtp_mirror->buffer); - if (raop_rtp_mirror->sps_pps) { - free(raop_rtp_mirror->sps_pps); - } free(raop_rtp_mirror); } }