@@ -1104,57 +1104,6 @@ static int media_player_find_file_begin(struct media_player *mp) {
11041104static bool media_player_read_packet (struct media_player * mp ) {
11051105 if (!mp -> coder .fmtctx )
11061106 return true;
1107- // Handle raw RTP file playback
1108- if (mp -> coder .audio_raw_rtp_mode ) {
1109- // Check if we have more data
1110- if (mp -> coder .audio_raw_rtp_pos >= mp -> coder .audio_raw_rtp_data .len ) {
1111- ilog (LOG_DEBUG , "End of raw RTP file reached" );
1112- return true;
1113- }
1114-
1115- // Calculate bytes to read (one frame)
1116- size_t bytes_to_read = MIN (mp -> coder .audio_raw_rtp_frame_size ,
1117- mp -> coder .audio_raw_rtp_data .len - mp -> coder .audio_raw_rtp_pos );
1118- // Allocate packet
1119- mp -> coder .pkt = av_packet_alloc ();
1120- if (!mp -> coder .pkt ) {
1121- ilog (LOG_ERR , "Failed to allocate packet" );
1122- return true;
1123- }
1124-
1125- // Fill packet with raw RTP data
1126- if (av_new_packet (mp -> coder .pkt , bytes_to_read ) < 0 ) {
1127- ilog (LOG_ERR , "Failed to create packet" );
1128- av_packet_free (& mp -> coder .pkt );
1129- return true;
1130- }
1131- if (bytes_to_read > 0 ) {
1132- memcpy (mp -> coder .pkt -> data ,
1133- mp -> coder .audio_raw_rtp_data .s + mp -> coder .audio_raw_rtp_pos ,
1134- bytes_to_read );
1135- }
1136- if (bytes_to_read < mp -> coder .audio_raw_rtp_frame_size ) {
1137- // Pad with silence if needed
1138- memset (mp -> coder .pkt -> data + bytes_to_read ,
1139- mp -> coder .silence_byte ,
1140- mp -> coder .audio_raw_rtp_frame_size - bytes_to_read );
1141- ilog (LOG_DEBUG , "Padding %zu bytes of silence" ,
1142- mp -> coder .audio_raw_rtp_frame_size - bytes_to_read );
1143- }
1144- mp -> coder .audio_raw_rtp_pos += bytes_to_read ;
1145-
1146- // Simulate packet timing (20ms per frame)
1147- mp -> coder .pkt -> pts = mp -> last_frame_ts ;
1148- mp -> coder .pkt -> duration = 160 ;
1149- mp -> last_frame_ts += mp -> coder .pkt -> duration ;
1150- // Process packet
1151- media_player_coder_add_packet (& mp -> coder , media_player_add_packet , mp );
1152- av_packet_free (& mp -> coder .pkt );
1153-
1154- // Schedule next read in 20ms
1155- mp -> next_run = rtpe_now + 20000 ;
1156- return false;
1157- }
11581107
11591108 int ret = av_read_frame (mp -> coder .fmtctx , mp -> coder .pkt );
11601109 if (ret < 0 ) {
@@ -1283,18 +1232,17 @@ static bool media_player_play_start(struct media_player *mp, const rtp_payload_t
12831232 return true;
12841233
12851234 mp -> next_run = rtpe_now ;
1286- if (!mp -> coder .audio_raw_rtp_mode ) {
1287- // give ourselves a bit of a head start with decoding
1288- mp -> next_run -= 50000 ;
1289-
1290- // if start_pos is positive, try to seek to that position
1291- if (mp -> opts .start_pos > 0 ) {
1292- ilog (LOG_DEBUG , "Seeking to position %lli" , mp -> opts .start_pos );
1293- av_seek_frame (mp -> coder .fmtctx , 0 , mp -> opts .start_pos , 0 );
1294- }
1295- else // in case this is a repeated start
1296- av_seek_frame (mp -> coder .fmtctx , 0 , 0 , 0 );
1235+ // give ourselves a bit of a head start with decoding
1236+ mp -> next_run -= 50000 ;
1237+
1238+ // if start_pos is positive, try to seek to that position
1239+ if (mp -> opts .start_pos > 0 ) {
1240+ ilog (LOG_DEBUG , "Seeking to position %lli" , mp -> opts .start_pos );
1241+ av_seek_frame (mp -> coder .fmtctx , 0 , mp -> opts .start_pos , 0 );
12971242 }
1243+ else // in case this is a repeated start
1244+ av_seek_frame (mp -> coder .fmtctx , 0 , 0 , 0 );
1245+
12981246 media_player_read_packet (mp );
12991247
13001248 return true;
@@ -1527,61 +1475,72 @@ static mp_cached_code __media_player_add_file(struct media_player *mp,
15271475 return MPC_OK ;
15281476}
15291477
1478+ struct rtp_payload_data {
1479+ int pt ; // RTP payload type
1480+ const char ffmpeg_codec_name [6 ]; // Codec name (case-sensitive)
1481+ enum AVMediaType codec_type ;// Media type
1482+ enum AVCodecID codec_id ; // FFmpeg codec ID
1483+ int sample_rate ; // Sample rate
1484+ int channels ; // Default channels
1485+ };
1486+
1487+ const struct rtp_payload_data rtp_payload_types [] = {
1488+ {0 , "mulaw" , AVMEDIA_TYPE_AUDIO , AV_CODEC_ID_PCM_MULAW , 8000 , 1 },
1489+ {8 , "alaw" , AVMEDIA_TYPE_AUDIO , AV_CODEC_ID_PCM_ALAW , 8000 , 1 },
1490+ {9 , "g722" , AVMEDIA_TYPE_AUDIO , AV_CODEC_ID_ADPCM_G722 , 8000 , 1 },
1491+ {18 , "g729" , AVMEDIA_TYPE_AUDIO , AV_CODEC_ID_G729 , 8000 , 1 },
1492+ {-1 , "" , AVMEDIA_TYPE_UNKNOWN , AV_CODEC_ID_NONE , -1 , -1 }
1493+ };
1494+
1495+ // Helper function to find codec configuration
1496+ static const struct rtp_payload_data * find_rtp_payload_data (const str * codec_str ) {
1497+ // Check static payload types
1498+ for (int i = 0 ; rtp_payload_types [i ].pt != -1 ; i ++ ) {
1499+ if (str_cmp (codec_str , rtp_payload_types [i ].ffmpeg_codec_name ) == 0 ) {
1500+ return & rtp_payload_types [i ];
1501+ }
1502+ }
1503+ ilog (LOG_ERR , "Unsupported codec: '" STR_FORMAT "'" , STR_FMT (codec_str ));
1504+ return NULL ;
1505+ }
1506+
15301507static bool __media_player_open_audio_raw_rtp_file (struct media_player * mp , media_player_opts_t opts ) {
15311508 // Validate codec
15321509 if (!opts .audio_raw_rtp_codec .len ) {
15331510 ilog (LOG_ERR , "Raw RTP playback requires codec specification" );
15341511 return false;
15351512 }
1536-
1537- // Convert file path
1538- char file_path [PATH_MAX ];
1539- snprintf (file_path , sizeof (file_path ), STR_FORMAT , STR_FMT (& opts .audio_raw_rtp_file ));
15401513
1541- // Open file
1542- FILE * f = fopen ( file_path , "rb" );
1543- if (!f ) {
1544- ilog (LOG_ERR , "Failed to open raw RTP file: %s " , file_path );
1514+ // Find codec configuration
1515+ const struct rtp_payload_data * payload_data = find_rtp_payload_data ( & opts . audio_raw_rtp_codec );
1516+ if (!payload_data || payload_data -> codec_id == AV_CODEC_ID_NONE ) {
1517+ ilog (LOG_ERR , "Codec '" STR_FORMAT "' is not supported by FFmpeg " , STR_FMT ( & opts . audio_raw_rtp_codec ) );
15451518 return false;
15461519 }
1520+
1521+ // Convert file path
1522+ char file_path [PATH_MAX ];
1523+ snprintf (file_path , sizeof (file_path ), STR_FORMAT , STR_FMT (& opts .audio_raw_rtp_file ));
15471524
1548- // Get file size
1549- fseek (f , 0 , SEEK_END );
1550- long file_size = ftell (f );
1551- fseek (f , 0 , SEEK_SET );
1552- // Read entire file into memory
1553- char * file_data = malloc (file_size );
1554- if (!file_data || fread (file_data , 1 , file_size , f ) != file_size ) {
1555- ilog (LOG_ERR , "Failed to read raw RTP file" );
1556- fclose (f );
1557- free (file_data );
1525+ AVInputFormat * iformat = av_find_input_format (opts .audio_raw_rtp_codec .s );
1526+ if (!iformat ) {
1527+ ilog (LOG_ERR , "Failed to find input format:'" STR_FORMAT "'" , STR_FMT (& opts .audio_raw_rtp_codec ));
15581528 return false;
15591529 }
1560- fclose (f );
1561-
1562- // Store in player context
1563- mp -> coder .audio_raw_rtp_data .s = file_data ;
1564- mp -> coder .audio_raw_rtp_data .len = file_size ;
1565- mp -> coder .audio_raw_rtp_pos = 0 ;
1566- // Set codec parameters based on input
1567- if (opts .audio_raw_rtp_codec .len == 4 && strncasecmp (opts .audio_raw_rtp_codec .s , "PCMU" , 4 ) == 0 ) {
1568- mp -> coder .audio_raw_rtp_codec = AV_CODEC_ID_PCM_MULAW ;
1569- mp -> coder .audio_raw_rtp_frame_size = 160 ; // 20ms frames
1570- mp -> coder .silence_byte = 0xFF ; // μ-law silence
1571- mp -> coder .time_base = (AVRational ){1 , 8000 }; // Default for 8kHz audio
1572- }
1573- else if (opts .audio_raw_rtp_codec .len == 4 && strncasecmp (opts .audio_raw_rtp_codec .s , "PCMA" , 4 ) == 0 ) {
1574- mp -> coder .audio_raw_rtp_codec = AV_CODEC_ID_PCM_ALAW ;
1575- mp -> coder .audio_raw_rtp_frame_size = 160 ; // 20ms frames
1576- mp -> coder .silence_byte = 0x55 ; // A-law silence
1577- mp -> coder .time_base = (AVRational ){1 , 8000 }; // Default for 8kHz audio
1578- }
1579- else {
1580- ilog (LOG_ERR , "Unsupported raw RTP codec: " STR_FORMAT , STR_FMT (& opts .audio_raw_rtp_codec ));
1581- free (file_data );
1530+
1531+ int ret = avformat_open_input (& mp -> coder .fmtctx , file_path , iformat , NULL );
1532+ if (ret < 0 ) {
1533+ ilog (LOG_ERR , "Raw RTP playback failing in avformat_open_input" );
1534+ return false;
1535+ }
1536+
1537+ if (!mp -> coder .fmtctx -> streams || !mp -> coder .fmtctx -> streams [0 ]) {
1538+ ilog (LOG_ERR , "No streams found in input file" );
15821539 return false;
15831540 }
1584-
1541+ mp -> coder .fmtctx -> streams [0 ]-> time_base = (AVRational ){1 , payload_data -> sample_rate > 0 ? payload_data -> sample_rate : 8000 }; // Default for 8kHz audio;
1542+ mp -> coder .fmtctx -> streams [0 ]-> codecpar -> sample_rate = payload_data -> sample_rate ;
1543+
15851544 return true;
15861545}
15871546
@@ -1591,28 +1550,7 @@ static bool media_player_play_audio_raw_rtp_file(struct media_player *mp, media_
15911550 return false;
15921551
15931552 if (!__media_player_open_audio_raw_rtp_file (mp , opts ))
1594- return false;
1595-
1596- // Set up fake format context
1597- mp -> coder .fmtctx = avformat_alloc_context ();
1598- if (!mp -> coder .fmtctx ) {
1599- ilog (LOG_ERR , "Failed to alloc format context" );
1600- return false;
1601- }
1602-
1603- // Create a dummy stream
1604- AVStream * stream = avformat_new_stream (mp -> coder .fmtctx , NULL );
1605- if (!stream ) {
1606- ilog (LOG_ERR , "Failed to create stream" );
1607- return false;
1608- }
1609-
1610- // Set codec parameters
1611- stream -> time_base = mp -> coder .time_base ;
1612- stream -> codecpar -> codec_id = mp -> coder .audio_raw_rtp_codec ;
1613- stream -> codecpar -> codec_type = AVMEDIA_TYPE_AUDIO ;
1614- stream -> codecpar -> channels = 1 ;
1615- stream -> codecpar -> channel_layout = AV_CH_LAYOUT_MONO ;
1553+ return false;
16161554
16171555 mp -> coder .audio_raw_rtp_mode = true;
16181556 return media_player_play_start (mp , dst_pt , opts .codec_set );
0 commit comments