@@ -1104,57 +1104,6 @@ static int media_player_find_file_begin(struct media_player *mp) {
1104
1104
static bool media_player_read_packet (struct media_player * mp ) {
1105
1105
if (!mp -> coder .fmtctx )
1106
1106
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
- }
1158
1107
1159
1108
int ret = av_read_frame (mp -> coder .fmtctx , mp -> coder .pkt );
1160
1109
if (ret < 0 ) {
@@ -1283,18 +1232,17 @@ static bool media_player_play_start(struct media_player *mp, const rtp_payload_t
1283
1232
return true;
1284
1233
1285
1234
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 );
1297
1242
}
1243
+ else // in case this is a repeated start
1244
+ av_seek_frame (mp -> coder .fmtctx , 0 , 0 , 0 );
1245
+
1298
1246
media_player_read_packet (mp );
1299
1247
1300
1248
return true;
@@ -1527,61 +1475,72 @@ static mp_cached_code __media_player_add_file(struct media_player *mp,
1527
1475
return MPC_OK ;
1528
1476
}
1529
1477
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
+
1530
1507
static bool __media_player_open_audio_raw_rtp_file (struct media_player * mp , media_player_opts_t opts ) {
1531
1508
// Validate codec
1532
1509
if (!opts .audio_raw_rtp_codec .len ) {
1533
1510
ilog (LOG_ERR , "Raw RTP playback requires codec specification" );
1534
1511
return false;
1535
1512
}
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 ));
1540
1513
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 ) );
1545
1518
return false;
1546
1519
}
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 ));
1547
1524
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 ));
1558
1528
return false;
1559
1529
}
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" );
1582
1539
return false;
1583
1540
}
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
+
1585
1544
return true;
1586
1545
}
1587
1546
@@ -1591,28 +1550,7 @@ static bool media_player_play_audio_raw_rtp_file(struct media_player *mp, media_
1591
1550
return false;
1592
1551
1593
1552
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;
1616
1554
1617
1555
mp -> coder .audio_raw_rtp_mode = true;
1618
1556
return media_player_play_start (mp , dst_pt , opts .codec_set );
0 commit comments